You can extend existing business classes without modifying their source code. For instance, when you work with an assembly that contains persistent classes.
This example modifies business classes declared in a separate project as follows:
- Adds an attribute (DefaultClassOptionsAttribute)
- Creates a simple persistent property (
NewIntField
) - Creates reference and collection properties linked by an association (one-to-many relationship between
PersistentObject1
andPersistentObject2
classes)
Implementation Details
- Populate the AdditionalExportedTypes property with types from external storage to add them to the application.C#
this.AdditionalExportedTypes.Add(typeof(MyXPOClassLibrary.PersistentObject1)); this.AdditionalExportedTypes.Add(typeof(MyXPOClassLibrary.PersistentObject2));
- Modify the added types as follows:
- Call the AddAttribute method to add an attribute to an existing class.
Note that by design you cannot dynamically add or remove theOptimisticLocking
orDeferredDeletion
attribute.C#ITypeInfo typeInfo1 = typesInfo.FindTypeInfo(typeof(PersistentObject1)); typeInfo1.AddAttribute(new DevExpress.Persistent.Base.DefaultClassOptionsAttribute());
- Call the CreateMember method to create a new simple persistent property.C#
IMemberInfo memberInfo0 = typeInfo1.FindMember("NewIntField"); if (memberInfo0 == null) { typeInfo1.CreateMember("NewIntField", typeof(int)); }
- Use both AddAttribute and CreateMember methods to create new reference and collection properties linked by an association.C#
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); }
- Call the AddAttribute method to add an attribute to an existing class.
- Call the RefreshInfo(Type) method to refresh metadata for the modified types.C#
typesInfo.RefreshInfo(typeof(PersistentObject1)); typesInfo.RefreshInfo(typeof(PersistentObject2));
Files to Review
Documentation
- Ways to Add a Business Class
- Use Metadata to Customize Business Classes Dynamically
- Access Business Object Metadata
- How to create business classes at runtime based on predefined configurations or allow user to define custom members via the application UI
- How to define a custom member for a domain component (DC) at runtime?
Does this example address your development requirements/objectives?
(you will be redirected to DevExpress.com to submit your response)
Example Code
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); }
}
}
}
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); }
}
}
}
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));
}
}