Scenarios
See real user scenarios in the following tickets:
Creating Users Defined Fields at Runtime
Create Dynamic Database Fields at runtime in XAF
XPO Dynamically built classes
XAF enduser design
Custom Fields that change based on properties of a Business Object
Solutions
Register modules and classes at runtime
1. Existing modules and business classes.
For more information on how to register modules and classes in the application dynamically (for instance, in code or configuration file), refer to the following help topics:
Ways to Add a Business Class ("Add All Classes from an Assembly in Code" | "Add a Certain Class from an Assembly in Code" )
Ways to Register a Module.
This API makes it possible to define a customer-tailored application configuration at runtime for certain scenarios. Take special note that in ASP.NET apps, the use of dynamically loaded XAF modules or business classes may require restarting an application pool on IIS (to update the Application Model and other internal infrastructure of an XAF application).
2. New modules and business classes.
There are no built-in options to create new custom modules and classes from scratch in the application UI or code. Note that the XPDictionary.CreateClass API cannot be used here as this method just creates a metadata record (the corresponding XPClassInfo.ClassType always returns the base class type) while in many places XAF expects a real .NET Framework type. You can still use the standard System.Reflection.Emit.AssemblyBuilder API to build classes and there is a good third-party example: http://www.expandframework.com/#worldcreator. This open-source WorldCreator module can create new assemblies on the fly as you create them in your Visual Studio and later configure using the Model Editor.
Create custom class properties at runtime
To define custom fields for existing business classes, use the Model Editor tool or override the CustomizeTypesInfo(ITypesInfo) method as described at Concepts > Business Model Design > Types Info Subsystem > Customize Business Object's Metadata. The built-in Model Editor tool is supposed to be used by developers or application administrators, so there is no special configuration UI for regular users. It is still possible to implement a custom-tailored solution and configuration UI by using the Types Info System APIs.
Changes to types metadata are forbidden while the application is running. We recommend that you restart the application after modifying your metadata customization storage to apply changes. All customizations made in the CustomizeTypesInfo method are taken into account by the XAF built-in database updater. Since database is a shared resource, concurent schema modifications may lead to errors. When the application is deployed, it is better to avoid updating the database schema from multiple users simultaneously. For best results, disable automatic updates, and update the database by a separate tool (DBUpdater).
Layout, appearance and custom behavior for runtime class properties
Such custom members are not supposed to be automatically added into the views layout. It is fully up to you to customize the application's UI screens representations in the Application Model to achieve the correct layout. You can use Model Editor or create a Controllers to customize properties of the corresponding detail view item and list view column or their controls. For more information, refer to the following help topics:
Access Editor Settings,
Access Grid Control Properties,
View Items Layout Customization,
List View Columns Customization.
You can show/hide these custom fields or provide custom business logic using custom Controllers or appearance rules, if required. See also: Concepts > Data Manipulation and Business Logic > Ways to Implement Business Logic.
There are also various ways to customize layout and other options at runtime as per your business requirements:
1. Follow the Extend and Customize the Application Model in Code article and create a generator updater. Some relevant examples can be found in our FeatureCenter demo at "C:\Users\Public\Documents\DevExpress Demos 1X.X\Components\eXpressApp Framework\FeatureCenter\CS\FeatureCenter.Module\Actions\CustomLayoutGenarator.cs" and "C:\Users\Public\Documents\DevExpress Demos 1X.X\Components\eXpressApp Framework\FeatureCenter\CS\FeatureCenter.Module\Actions\CustomDetailViewLayoutGenarator.cs"
2. Use the Access the Application Model in Code approach to update Application Model on the XafApplication > UserDifferencesLoaded event (T271022).
How to read configuration metadata in the CustomizeTypesInfo method
Certain XAF customers store configuration data in the database tables or XML files and then establish runtime associations or add simple scalar fields as per the aforementioned documentation. To fetch class and property name information from a database, create IObjectSpace manually as described in the Access XAF Application Data in a non-XAF Application article or use pure XPO/ADO.NET APIs as without XAF. Once you obtain this information, you can add writeable and calculated properties for each of them using the CreateMember API. To query other tables in your for calculated properties, consider using Free Joins. To get a single property value from a collection, use aggregated functions ( Min, Max, Single).
1. IObjectSpace API:
C#public override void CustomizeTypesInfo(ITypesInfo typesInfo) {
base.CustomizeTypesInfo(typesInfo);
CalculatedPersistentAliasHelper.CustomizeTypesInfo(typesInfo);
string connectionString = ConfigurationManager.ConnectionStrings["MetadataConnectionString"].ConnectionString;
using(XPObjectSpaceProvider osProvider = new XPObjectSpaceProvider(connectionString, null)) {
using(IObjectSpace objectSpace = osProvider.CreateObjectSpace()) {
TypeInfo typeInfo = (TypeInfo)typesInfo.FindTypeInfo(typeof(YourExistingBusinessClass));
var additionalProperties = objectSpace.GetObjects<YourMetadataClass>();
foreach(var pi in additionalProperties) {
if(pi.IsCalculated) {
// Create a readonly member based on a criteria expression.
typeInfo.CreateMember(pi.CustomPropertyName, pi.CustomPropertyType, pi.CustomPropertyCriteriaExpression);
}
else {
// Create a writeable member.
typeInfo.CreateMember(pi.CustomPropertyName, pi.CustomPropertyType);
}
}
typesInfo.RefreshInfo(typeof(YourExistingBusinessClass));
}
}
}
Take special note that the middle-tier application client does not allow you to access data through the Object Space until a user logs on to the security system (T641574).
2. XPO API:
C#public override void CustomizeTypesInfo(ITypesInfo typesInfo) { // Based on T456632.
base.CustomizeTypesInfo(typesInfo);
List<Type> toRefresh = new List<Type>();
string cs = ConfigurationManager.ConnectionStrings["MetadataConnectionString"].ConnectionString;
IDisposable[] toDispose = null;
try {
XPDictionary dict = new ReflectionDictionary();
dict.GetDataStoreSchema(typeof(YourMetadataClass));
using(IDataLayer metaDataLayer = XpoDefault.GetDataLayer(cs, dict, DevExpress.Xpo.DB.AutoCreateOption.None, out toDispose)) {
using(Session session = new Session(metaDataLayer)) {
XPCollection<YourMetadataClass> additionalProperties = new XPCollection<YourMetadataClass>(session);
foreach(var pi in additionalProperties) {
ITypeInfo ti = typesInfo.FindTypeInfo(pi.ObjectType);
if(ti == null)
continue;
IMemberInfo mi = ti.FindMember(pi.CustomPropertyName);
if(mi == null) {
ti.CreateMember(pi.Name, pi.CustomPropertyType);
if(!toRefresh.Contains(ti.Type)) {
toRefresh.Add(ti.Type);
}
}
}
}
}
foreach(Type t in toRefresh) {
XafTypesInfo.Instance.RefreshInfo(t);
}
}
catch { }
finally {
if(toDispose != null) {
foreach(var obj in toDispose) {
obj.Dispose();
}
}
}
}
Other options if you do not need the most of the standard XAF functionality
If you do not need the full CRUD capabilities, security, validation, reporting, data analysis, etc. for your user-defined classes and fields, then there may be a bit simpler solutions, but with certain limitations. For example, you can integrate a custom control that renders objects from its data source as separate editors. Please refer to the following ticket for additional information: How to add custom properties to a DetailView dynamically at runtime.
Search keywords
CustomizeTypesInfo, CreateMember, CreateClass, class, type, member, property, user-defined, TypesInfo, ITypeInfo, IMemberInfo, XPClassInfo, runtime, dynamic, dynamically, config, database, XML, file, restart, reload, model