How to implement Services Model Wrappers

This topic describes rules and best practices utilized to implement Service Model Wrappers.

  • The module, in which Services Model Wrapper is implemented, should include Xafari.BC.Xas.XafariBCXasModule from the assembly of the same name;
  • The created class should be a descendant of the Xafari.BC.Xas.Services.ServiceCfgObject<T, TModel> base class;
  • DevExpress.ExpressApp.DC.DomainComponentAttribute should be applied to the class;
  • The class should contain a default constructor allowing the framework to create instances via the XafariNonPersistentObjectSpace.CreateObject<T>() method. When creating a new Services Model Wrapper instance by the standard NewObjectViewController (via the Add -> New Item dialog), a special ServiceCfgListViewController initializes the ServiceCfgObject.Model property. The instances of the Services Model Wrapper classes are generated by ServiceCfgObjectsService. Processing the XafariNonPersistentObjectSpace events (such as ObjectGetting or ObjectByKeyGetting), the service creates instances, for which there are corresponding nodes in the Services Model.
  • The implementation of the class properties being mapped onto the corresponding node of the Model is performed quite similarly to the properties of a persistent XPO class — by using the GetPropertyValue and SetPropertyValue methods. In case of an attempt to save the property value that is not present in the corresponding node of the Services Model, the InvalidOperationException is generated.
  • The properties that display the values of other nodes of the Model (e.g. the list of BOModel objects) utilize a special property editor — Xafari.BC.Win.Editors.ModelNodesLookupPropertyEditor. The editor is in the Xafari.BC.Win.XafariBCWinModule.dll assembly. Accordingly, Xafari.BC.Win.XafariBCWinModule should be added to the module that contains the wrapper class. To fill the lookup collection, the editor automatically uses the data source of the corresponding node of the Model. That is why it is not necessary to specify the data source in the code of the wrapper class.
  • Nested collections are implemented by the ServiceCfgObject<T, TModel>.GetCollection() method. It is necessary to apply DevExpress.ExpressApp.DC.AggregatedAttribute to the wrapper class property that represents a nested collection. In the UI, this attribute makes the behavior of the nested collections identical to the aggregated ones.
  • The naming rule influences the properties mapping of both the wrapper class and the Service Model nodes. The class property name should match the property name in the Model. The property types should also match each other to allow the ServiceCfgObject reading and editing all changes to the Model. The property value is serialized while saving and can be later read and mapped onto an object’s property according to the mentioned naming rule.

The application that uses Services Model Wrappers should also utilize the Xafari.XafariNonPersistentObjectSpaceProvider.