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
- By design you cannot dynamically add or remove the OptimisticLocking and DeferredDeletion attributes.
- 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
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));
}
}