Skip to main content
A newer version of this page is available. .
.NET Standard 2.0+

ModuleBase Class

The base class for XAF modules.

Namespace: DevExpress.ExpressApp

Assembly: DevExpress.ExpressApp.v21.2.dll

NuGet Package: DevExpress.ExpressApp

Declaration

[ToolboxTabName("DX.21.2: XAF Modules")]
public class ModuleBase :
    Component,
    ISupportSetup

Remarks

The presence of a ModuleBase class descendant in a standard Class Library project indicates that this project represents a module. Controllers, View Items and other XAF elements are loaded in the Application Model only when they are declared in modules. In addition, modules allow you to customize the Application Model when it is being loaded. For this purpose, override the ModuleBase class methods.

The following list represents the primary capabilities available by overriding the appropriate ModuleBase methods:

  • Speed-up Collecting Types Declared Within the Module

    Override the GetDeclaredExportedTypes method to customize the default behavior of exporting of all the assembly’s business classes to the Application Model.

    Override the GetDeclaredControllerTypes method to customize the default behavior of exporting of all the assembly’s Controllers to the Application Model.

    Override the protected GetRegularTypes method to return types that are declared within the module and are supposed to be collected automatically (business objects, DbContext descendants, Controllers, List and Property Editors, etc.). By default, this method returns all the types declared within the current module. Internally, it uses reflection for this purpose. You can improve the application performance by providing the list of types manually. Note that if you override the GetRegularTypes method, types declared within the module are no longer collected automatically, and you should manually register each new business object, Controller or Editor within this method. However, it is not necessary to register types that are already returned by overridden GetDeclaredExportedTypes and GetDeclaredControllerTypes methods.

  • Load Additional Modules

    Together with the current module, add modules with the required features to the Application Model using the GetRequiredModuleTypesCore method. The current module should have a reference to the modules to be added.

  • Add Custom Nodes and Properties

    Override the ModuleBase.ExtendModelInterfaces method to add the required nodes or properties. If you need to add a custom node, first declare its interface by inheriting the IModelNode interface. See the Extend and Customize the Application Model in Code topic for details.

  • Update the Application Model Using the Generator Updaters

    Override the ModuleBase.AddGeneratorUpdaters method to add Generator Updaters which update the Application Model.

  • Add External Business Objects and Controllers to the Application Model

    Override the GetDeclaredControllerTypes and GetDeclaredExportedTypes methods as shown below:

    namespace MySolution.Module {  
        public sealed partial class MySolutionModule : ModuleBase {  
            protected override IEnumerable<Type> GetDeclaredControllerTypes() {  
                var originalList = (Type[])base.GetDeclaredControllerTypes();  
                var newList = originalList.ToList();  
                newList.Add(typeof(ClassLibrary1.CustomController));  
                return newList;  
            }  
            protected override IEnumerable<Type> GetDeclaredExportedTypes() {  
                var originalList = base.GetDeclaredExportedTypes();  
                var newList = originalList.ToList();  
                newList.Add(typeof(ClassLibrary1.MyCustomTask));  
                return newList;  
            }  
        }  
    }  
    
  • Update the Database Using the Module Updaters

    Override the ModuleBase.GetModuleUpdaters method to add ModuleUpdater objects that update the database.

  • Customize Types Info Subsystem

    Override the ModuleBase.CustomizeTypesInfo method to customize information on a particular class or property, before it is loaded to the Application Model.

  • Register List or Property Editor

    Override the protected RegisterEditorDescriptor method to switch off the reflection mechanism, which collects information on the types decorated by the ListEditorAttribute and PropertyEditorAttribute attributes. This speeds up your application start. Note that in this case the Editors which are decorated by these attributes are not registered.

    Use the EditorDescriptorsFactory.RegisterListEditorAlias and EditorDescriptorsFactory.RegisterListEditor methods to register your List Editor with its alias.

    To register a Property Editor, use the EditorDescriptorsFactory.RegisterPropertyEditorAlias and EditorDescriptorsFactory.RegisterPropertyEditor methods.

    You can associate the EditorAliases enumerator value or a custom alias with a target type. It is possible to register one alias for WinForms and ASP.NET Web Forms Editors in the base module project and locate suitable Editors in the platform-dependent projects. If you have platform-agnostic Editors for a specific type, specify a special string alias to use them in a platform-independent module. Note that the Editor registered for the Object type is used to display objects and properties of a type for which another Editor is not specified.

    The following example demonstrates how to register a default List Editor.

    public class MyModule : ModuleBase {
        //...
        protected override void RegisterEditorDescriptors(EditorDescriptorsFactory 
        editorDescriptorsFactory) {
            editorDescriptorsFactory.RegisterListEditorAlias("CustomListEditorAlias",
            typeof(object), true);
            editorDescriptorsFactory.RegisterListEditor("CustomListEditorAlias", 
            typeof(object), typeof(GridListEditor), true);
        }
    }
    

    See the list below to modify this example in accordance with your purposes.

    • Set the methods’ elementType parameter to the Object type and set the isDefaultEditor parameter to false to add this Editor to the IModelViews.DefaultListEditor list of default List Editors. Then, you can choose this Editor in the Model Editor.
    • To register the default List Editor for objects of a specific type, pass the target type to the methods’ elementType parameter and set the isDefaultEditor parameter to true to mark this Editor as default for the type.
    • Specify the target type in the methods’ elementType parameter and set the isDefaultEditor parameter to false to add the List Editor to the IModelClass.EditorType list of List Editors for the specified type. Then, you can choose this Editor in the Model Editor.
    • Use the classHandler parameter of the RegisterListEditorAlias method if you want to register a number of Editors for one type and choose the appropriate Editor according to the logic implemented in it. In different situations, the Editor satisfying the conditions is applied to current type first.

      public class MyModule : ModuleBase {
          //...
          protected override void RegisterEditorDescriptors(EditorDescriptorsFactory editorDescriptorsFactory) {
              //...
              editorDescriptorsFactory.RegisterListEditorAlias("MyAlias", typeof(object), IsCriteriaProperty); 
          }
          private static bool IsCriteriaProperty(IModelClass modelClass) {
              //...    
          }
      }
      

    The following example demonstrates how to register a default Property Editor.

    public class MyModule : ModuleBase {
        //...
        protected override void RegisterEditorDescriptors(EditorDescriptorsFactory 
        editorDescriptorsFactory) {
            //...
            editorDescriptorsFactory.RegisterPropertyEditorAlias("CustomPropertyEditorAlias",
            typeof(object), true);
            editorDescriptorsFactory.RegisterPropertyEditor("CustomPropertyEditorAlias", 
            typeof(object), typeof(DefaultPropertyEditor), true);
        }
    }
    

    Note

    To set your Property Editor as default for properties with protected content, implement the IProtectedContentEditor interface in your Property Editor.

    See the list below to modify this example in accordance with your purposes.

    • Set the methods’ elementType parameter set to the Object type and set the isDefaultEditor parameter to false to add this Property Editor to the IModelRegisteredViewItem.DefaultItemType list of default Property Editors orIModelRegisteredPropertyEditors.ProtectedContentPropertyEditor if your Editor is for the properties with protected content. Then, you can choose this Editor in the Model Editor.
    • To register the default Property Editor for the properties of a specific type, pass the target type to the methods’ elementType parameter and set the isDefaultEditor parameter to false to mark this Editor as default for the type.
    • Specify the target type in the methods’ elementType parameter and set the isDefaultEditor parameter to false to add the Property Editor to the IModelRegisteredPropertyEditor.EditorType list of Property Editors for the specified type. Then, you can choose this Editor in the Model Editor.
    • Use the memberHandler parameter of the RegisterPropertyEditorAlias method if you want to register a number of Editors for properties of one type and choose the appropriate Editor according to the logic implemented in it. In different situations, the Editor satisfying the conditions is applied to current type first. Editors registered with this parameter have priority over Editors registered without it. For the Editor registered with the memberHandler parameter, the new node is created in the Model Editor’s View Items | PropertyEditors node.

      public class MyModule : ModuleBase {
          //...
          protected override void RegisterEditorDescriptors(EditorDescriptorsFactory 
          editorDescriptorsFactory) {
              //... 
              editorDescriptorsFactory.RegisterPropertyEditorAlias("MyAlias", 
              typeof(DateTime), IsMemberCompatibleHandler);
          }
          private static bool IsMemberCompatibleHandler(IModelMember modelMember) {
              //...
          }
      }
      

You do not have to create instances of the ModuleBase class descendants. They are created automatically.

To add a module to your application, use the Module Designer or Application Designer.

Add External Business Objects and Controllers to the Application Model

XAF uses reflection to collect classes and Controllers from each module and build an Application Model. Use the following techniques to customize this process:

  • Use the ModuleBase.AdditionalControllerTypes and ModuleBase.AdditionalExportedTypes properties to specify business classes and Controllers that should be loaded to the Application Model:

    File: MySolution.Module/Module.cs(.vb)

    namespace MySolution.Module {
        public sealed partial class MySolutionModule : ModuleBase {
            public MySolutionModule() {
                InitializeComponent();
                AdditionalControllerTypes.Add(typeof(ClassLibrary1.Controller1));
                AdditionalExportedTypes.Add(typeof(ClassLibrary1.PersistentClass1));
            }
        // ...
        }
    }
    

    In .NET Framework applications, you can open the Module Designer and modify the Controllers and Exported types sections.

    moduledesignerModule Designer.

  • Override the GetDeclaredControllerTypes and GetDeclaredExportedTypes methods of the ModuleBase class to add external business objects and Controllers to the Application Model:

    File: MySolution.Module/Module.cs(.vb)

    namespace MySolution.Module {  
        public sealed partial class MySolutionModule : ModuleBase {  
            protected override IEnumerable<Type> GetDeclaredControllerTypes() {  
                var originalList = (Type[])base.GetDeclaredControllerTypes();  
                var newList = originalList.ToList();  
                newList.Add(typeof(ClassLibrary1.CustomController));  
                return newList;  
            }  
            protected override IEnumerable<Type> GetDeclaredExportedTypes() {  
                var originalList = base.GetDeclaredExportedTypes();  
                var newList = originalList.ToList();  
                newList.Add(typeof(ClassLibrary1.MyCustomTask));  
                return newList;  
            }  
        }  
    }  
    
See Also