# ModelBuilders - Inline approach

This approach is very useful when applying just a couple of attributes to a business object. It is both quick and it avoids the requirement to create an additional (buddy)class.

# Class Level

The following code samples illustrate the use of inline ModelBuilders to replace Class Level attributes.











 
 















using System;
using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Xpo;

namespace MainDemo.Module.BusinessObjects
{
    [DefaultClassOptions]
    [ModelDefault("Caption", "Task")]
    public class DemoTask : BaseObject 
    {
        public DemoTask(Session session) : base(session) { }

        [ToolTip("View, assign or remove contacts for the current task")]
        [Association("Contact-DemoTask")]
        public XPCollection<Contact> Contacts
        {
            get
            {
                return GetCollection<Contact>(nameof(Contacts));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

In order to replace the two class level attributes it is necessary to override the 'CustomTypesInfo' method utilising the 'ModelBuilder.Create()' method to create and inline 'ModelBuilder'.

TIP

It is a requirement that the 'ModelBuilder' 'Build' method is called at the end in order to refresh the 'ITypesInfo' instance.

But first we need to import the correct namespace by using the using Xenial.Framework.ModelBuilders; statement.









 











 
 
 
 




using System;
using System.Collections.Generic;
using System.Linq;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;

using Xenial.Framework;
using Xenial.Framework.ModelBuilders;

using MainDemo.Module.BusinessObjects;

namespace MyApplication.Module
{
    public class MyApplicationModule : ModuleBase
    {
        public override void CustomizeTypesInfo(ITypesInfo typesInfo)
        {
            base.CustomizeTypesInfo(typesInfo);

            ModelBuilder.Create<DemoTask>(typesInfo)
                .WithDefaultClassOptions()
                .HasCaption("Task")
                .Build();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Using the built in methods WithDefaultClassOptions and HasCaption those attributes can be applied to the business class and once done the attributes themselves can be removed from the business object's code.











 
 















using System;
using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Xpo;

namespace MainDemo.Module.BusinessObjects
{
    // [DefaultClassOptions]
    // [ModelDefault("Caption", "Task")]
    public class DemoTask : BaseObject
    {
        public DemoTask(Session session) : base(session) { }

        [ToolTip("View, assign or remove contacts for the current task")]
        [Association("Contact-DemoTask")]
        public XPCollection<Contact> Contacts
        {
            get
            {
                return GetCollection<Contact>(nameof(Contacts));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# Property Level

Property level attributes require a slightly different approach.

















 










using System;
using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Xpo;

namespace MainDemo.Module.BusinessObjects
{
    [DefaultClassOptions]
    [ModelDefault("Caption", "Task")]
    public class DemoTask : BaseObject 
    {
        public DemoTask(Session session) : base(session) { }

        [ToolTip("View, assign or remove contacts for the current task")]
        [Association("Contact-DemoTask")]
        public XPCollection<Contact> Contacts
        {
            get
            {
                return GetCollection<Contact>(nameof(Contacts));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Once again the 'CustomizeTypesInfo' is overidden but in this instance the static ModelBuilder.Create<T>() method is called to create an inline model builder. It returns an instance of a ModelBuilder that can be used to apply property attributes as well. Use the builder.For(member => member.MemberName) linq like syntax to provide a refactor and type safe way to specify the property of the business object for which the attribute is to be removed.

As before add a reference to the correct namespace by using the using Xenial.Framework.ModelBuilders; statement.









 













 
 






using System;
using System.Collections.Generic;
using System.Linq;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;

using Xenial.Framework;
using Xenial.Framework.ModelBuilders;

using MainDemo.Module.BusinessObjects;

namespace MyApplication.Module
{
    public class MyApplicationModule : ModuleBase
    {
        public override void CustomizeTypesInfo(ITypesInfo typesInfo)
        {
            base.CustomizeTypesInfo(typesInfo);

            var builder = ModelBuilder.Create<DemoTask>(typesInfo);

            builder.For(m => m.Contacts)
                .HasTooltip("View, assign or remove contacts for the current task");

            builder.Build();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

Use the built in method HasTooltip to apply the attribute to the business class property. Once done the attribute can be removed from the code.

















 










using System;
using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Xpo;

namespace MainDemo.Module.BusinessObjects
{
    [DefaultClassOptions]
    [ModelDefault("Caption", "Task")]
    public class DemoTask : BaseObject
    {
        public DemoTask(Session session) : base(session) { }

        // [ToolTip("View, assign or remove contacts for the current task")]
        [Association("Contact-DemoTask")]
        public XPCollection<Contact> Contacts
        {
            get
            {
                return GetCollection<Contact>(nameof(Contacts));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# Summary

The use of 'imperative' code over traditional attributes allows attributes to be applied to code which may be in different assembly and potentially inaccesible, whilst retain all the advantages profferd by C# to increase maintainability (string interpolation, etc).

On completion the business object's code will be as follows:

using System;
using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Xpo;

namespace MainDemo.Module.BusinessObjects
{
    public class DemoTask : BaseObject
    {
        public DemoTask(Session session) : base(session) { }

        [Association("Contact-DemoTask")]
        public XPCollection<Contact> Contacts
        {
            get
            {
                return GetCollection<Contact>(nameof(Contacts));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;
using System.Linq;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;

using Xenial.Framework;
using Xenial.Framework.ModelBuilders;

using MainDemo.Module.BusinessObjects;

namespace MyApplication.Module
{
    public class MyApplicationModule : ModuleBase
    {
        public override void CustomizeTypesInfo(ITypesInfo typesInfo)
        {
            base.CustomizeTypesInfo(typesInfo);

            var builder = ModelBuilder.Create<DemoTask>(typesInfo)
                .WithDefaultClassOptions()
                .HasCaption("Task");

            builder
                .For(m => m.Contacts)
                .HasTooltip("View, assign or remove contacts for the current task");

            builder.Build();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32