Example E250
Visible to All Users

How to customize an XPO business model at runtime (Example)

Sometimes there is a requirement to extend existing business classes when you cannot modify their source code.

For instance, you have an assembly where some persistent classes are declared. You want to use it in your XAF application and add attributes, new members, etc…

Implementation Details

To use types from external assemblies, add them to the application as described in the Ways to Add a Business Class - Add Classes From a Business Class Library or Module article.

To see how to extend business classes at runtime, refer to the eXpressApp Framework > Concepts > Business Model Design > Types Info Subsystem > Use Metadata to Customize Business Classes Dynamically article.

This example demonstrates how to:

  • Add an attribute to an existing class
  • Create a new simple persistent property
  • Create new reference and collection properties linked by an association

Files to Review

Important notes

  1. By design you cannot dynamically add or remove the OptimisticLocking and DeferredDeletion attributes.
  2. Adding custom members for Domain Components (DC) should be done on the XafApplication.SettingUp event as described at How do I define a custom member for a domain component (DC) at runtime?.

Documentation

How to: Access Business Class Metadata

How to create business classes at runtime based on predefined configurations or allow user to define custom members via the application UI

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

CustomizeXPOModel/MyXPOClassLibrary/PersistentObject1.cs
C#
using System; using System.ComponentModel; using DevExpress.Xpo; namespace MyXPOClassLibrary { public class PersistentObject1 : XPObject { public PersistentObject1(Session session) : base(session) { // This constructor is used when an object is loaded from a persistent storage. // Do not place any code here. } public override void AfterConstruction() { base.AfterConstruction(); // Place here your initialization code. } private string _stringPropertyName; public string StringPropertyName { get { return _stringPropertyName; } set { SetPropertyValue(nameof(StringPropertyName), ref _stringPropertyName, value); } } private int _intPropertyName; public int IntPropertyName { get { return _intPropertyName; } set { SetPropertyValue(nameof(IntPropertyName), ref _intPropertyName, value); } } } }
CustomizeXPOModel/MyXPOClassLibrary/PersistentObject2.cs
C#
using System; using DevExpress.Xpo; namespace MyXPOClassLibrary { public class PersistentObject2 : XPObject { public PersistentObject2(Session session) : base(session) { // This constructor is used when an object is loaded from a persistent storage. // Do not place any code here. } public override void AfterConstruction() { base.AfterConstruction(); // Place here your initialization code. } private string _Name; public string Name { get { return _Name; } set { SetPropertyValue(nameof(Name), ref _Name, value); } } } }
CustomizeXPOModel/CustomizeXPOModel.Module/Module.cs
C#
using System.ComponentModel; using DevExpress.ExpressApp; using DevExpress.ExpressApp.DC; using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl; using DevExpress.ExpressApp.Model; using DevExpress.ExpressApp.Actions; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Updating; using DevExpress.ExpressApp.Model.Core; using DevExpress.ExpressApp.Model.DomainLogics; using DevExpress.ExpressApp.Model.NodeGenerators; using DevExpress.Xpo; using DevExpress.ExpressApp.Xpo; using MyXPOClassLibrary; namespace CustomizeXPOModel.Module; // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. public sealed class CustomizeXPOModelModule : ModuleBase { public CustomizeXPOModelModule() { // // CustomizeXPOModelModule // RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.SystemModule.SystemModule)); RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule)); RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule)); RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Validation.ValidationModule)); this.AdditionalExportedTypes.Add(typeof(MyXPOClassLibrary.PersistentObject1)); this.AdditionalExportedTypes.Add(typeof(MyXPOClassLibrary.PersistentObject2)); } public override IEnumerable<ModuleUpdater> GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB); return new ModuleUpdater[] { updater }; } public override void Setup(XafApplication application) { base.Setup(application); // Manage various aspects of the application UI and behavior at the module level. } public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo) { base.CustomizeTypesInfo(typesInfo); CalculatedPersistentAliasHelper.CustomizeTypesInfo(typesInfo); ITypeInfo typeInfo1 = typesInfo.FindTypeInfo(typeof(PersistentObject1)); typeInfo1.AddAttribute(new DevExpress.Persistent.Base.DefaultClassOptionsAttribute()); IMemberInfo memberInfo0 = typeInfo1.FindMember("NewIntField"); if (memberInfo0 == null) { typeInfo1.CreateMember("NewIntField", typeof(int)); } ITypeInfo typeInfo2 = typesInfo.FindTypeInfo(typeof(PersistentObject2)); IMemberInfo memberInfo1 = typeInfo1.FindMember("PersistentObject2s"); IMemberInfo memberInfo2 = typeInfo2.FindMember("PersistentObject1"); if (memberInfo1 == null) { memberInfo1 = typeInfo1.CreateMember("PersistentObject2s", typeof(DevExpress.Xpo.XPCollection<PersistentObject2>)); memberInfo1.AddAttribute(new DevExpress.Xpo.AssociationAttribute("PersistentObject1-PersistentObject2s", typeof(PersistentObject2)), true); memberInfo1.AddAttribute(new DevExpress.Xpo.AggregatedAttribute(), true); } if (memberInfo2 == null) { memberInfo2 = typeInfo2.CreateMember("PersistentObject1", typeof(PersistentObject1)); memberInfo2.AddAttribute(new DevExpress.Xpo.AssociationAttribute("PersistentObject1-PersistentObject2s", typeof(PersistentObject1)), true); } typesInfo.RefreshInfo(typeof(PersistentObject1)); typesInfo.RefreshInfo(typeof(PersistentObject2)); } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.