Tuesday, September 28, 2010

Calculated properties at runtime—TIMES 4

In this post you are going to see how you can use on more of eXpand powerfull features. 4 different ways for creating calculated runtime properties are avaliable.

  1. XPO way –>Using Code
    Take a note at the CreateCalculabeMember extension method at the code bellow

        public class CreateRuntimeCalculatedFieldController : ViewController {

            public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo) {

                base.CustomizeTypesInfo(typesInfo);

                var classInfo = XafTypesInfo.XpoTypeInfoSource.XPDictionary.GetClassInfo(typeof(Customer));

     

                if (classInfo.FindMember("SumOfOrderTotals")==null) {

                    var attributes = new Attribute[] {new PersistentAliasAttribute("Orders.Sum(Total)")};

                    classInfo.CreateCalculabeMember("SumOfOrderTotals", typeof(float), attributes);

                    typesInfo.RefreshInfo(typeof(Customer));

                }

            }

        }

  2. Using ModelDifference Module
    Setting IsRuntimeMember attribute will create a runtime member and setting the AliasExpression will convert it to a calculated member
    image
    Take a note here that you can easily create calculabe members for the whole application or for a user role or for just one user, depending which type of model is going to host your property
  3. Using WorldCreator extended members
    This approach can be used when u want to decorate your property with more attributes , since WorldCreator  supports much more than the model
    image image
  4. Using a WordCreator Dynamic Assembly
    this approach is the most powerfull one cause allows you also to change the code template as you see in the image bellow

    image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Wednesday, September 22, 2010

Model Distribution with IO Engine

ModelDifference module is one of the powerfull modules of eXpand . It really helps in managing your application models.

Scenario
Your application has been already distributed to your client and you no longer have access to the production database. Your client admin is responsible for that. But since development never stops as you know, you client asked for some model modification and some new application models (lets say 10) have been developed by your team and you want to sent them to the admin to update the application.

eXpand IO module is the right one for the job

Step1—Create a serialization graph to configure which objects/values you are going to export

In order to create a serialization graph for an object type you have 1st to create a Serialization Configuration Group, that is just a container to help you organize your graphs

image

Given that you want to export Models you have to create a graph for the ModelDifferenceObject persistent class

image

When you set the Type To Serialize editor value (1) IO module will automatically fill the values of the nested listview (2) by populating the properties of the Application Difference object, and also will create graphs for objects that are connected with Application Difference object (3)

Step2--Clean automatically created graph

You may wondering how the graphs in the number (3) of the above image are created. If you see the domain model of the ModelDifferenceObject you will see the relation between all these objects.

image

So what IO module does goes through all those relations and create graphs for each one of them, since due to object polymorphism it is impossible to know the type of the object from the start. But you do!! You know that you are interested to export only ModelDifferenceObjects and not RoleModelDifferenceObject or UserModelDifferenceObject so you could delete all other graphs as showh bellow

image

Step3—Choose Serialization Strategy

This screenshot are taken from eXpand feature center and as you see there are some properties that we may not want to export such as City,UserFilter,Skin. We can exclude them from the export process by choosing a DoNotSerialize strategy

image

Now for the  most interesting and hard step. As you see from the domain model above ModelDifferenceObject has M-1 relation with the PersistentApplication object, also by the name of PersistentApplication one can understand that the already distributed application already have that object and we not want to export its properties but only its key, so choosing a SerializeAsValue strategy will solve that one also

image

But we have not finish yet. If you think again what we did is export only the key of the PersistentApplication, but the key type is GUID meaning that the distributed application with the one from the which we are going to export will have different keys. To solve this one we have to go to the PersistentApplication Graph and change the key from Oid to UniqueName, thus IO engine will not get confused and will used the appropriate object

image

image

Step4 –Select and export models

Just go to a list view that has the objets you are interested to export and use the IO/Export action

Step 5—Import the exported objects

This process is very easy and only requires to use the IO/Import action and choose the xml file .

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Monday, September 20, 2010

Make your navigation behave

Xaf provides a very easy to configure navigation system and in this post i will speak about expand approach to make Xaf’s navigation system behave better than the one provided by default.

To enable eXpand extended navigation behaviour one can use the ViewShortcutProccesor attribute either at BO level or at View level as shown in the next image

image image

Now what this ViewShortcutProccesor can do to speed up your development?

  1. Navigate to a detailview using a ReadOnlyParameter

    image

    the above readonly parameter taken from eXpand feature center and is defined as

        public class ExternalApplicationKeyParameter : ReadOnlyParameter

        {

            public ExternalApplicationKeyParameter() : base("ExternalApplicationKey", typeof(Guid)) { }

     

            public override object CurrentValue {

                get {

                    return ((User) SecuritySystem.CurrentUser).Session.FindObject<ModelDifferenceObject>(

                            o => o.Name == "ExternalApplication" && o.PersistentApplication.Name == "ExternalApplication").Oid;

                }

            }

        }

     

  2. Navigate to a non persistent object detail view
    image
    the object can be designed as

        [NonPersistent]

        public class WelcomeObject

        {

        }

    or as

        [NonPersistent]

        public class WelcomeObject:XPBaseObject

        {

            public WelcomeObject(Session session) : base(session) {

            }

        }

  3. Browse objects directly from a detailview
    The navigation settings here are exaclty the same as the above but also the navigation actions of the detailview will be enabled, allowing you to navigate to the next record.
    if for the current type no objects are found a new one will be created
    image
  4. Navigate to a specific object/ collection of objects detailview
    Setting at ObjectKey the criteria of your choice  you can open a directly a detailview. If object not found a new one will be created again
    image
  5. Desing your navigation using class based attributes
    Using XpandNavigationItem you can design deep tree level menus by just decorating your class
    image
    the above declaration will create the navigation shown in the image bellow
    image
  6. Design time view cloning
    When building a real world application, most probably you are going to have multiple views for your object types. eXpand provides the CloneView class level attribute that can help you create cloned views at design time.

        [CloneViewAttribute(CloneViewType.ListView, "ConditionalControlAndMessage_ListView")]

        public class Customer : CustomerBase {

            public Customer(Session session) : base(session) {

            }

     

        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]

        public class CloneViewAttribute : Attribute, ISupportViewId {

            readonly CloneViewType _viewType;

            readonly string _viewId;

     

            public CloneViewAttribute(CloneViewType viewType, string viewId) {

                _viewType = viewType;

                _viewId = viewId;

            }

     

     

            public string ViewId {

                get { return _viewId; }

            }

     

     

            public CloneViewType ViewType {

                get { return _viewType; }

            }

     

            public string DetailView { get; set; }

        }

     

    the advantage of using CloneViewAttribute is that your cloned views are not created in the lastlayer, thus later changes on the view are noted easily . As you see in the next image only the NewColumn attribute is mark bold!!
    image 

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Wednesday, September 15, 2010

Conditional Member Level Security

DevExpress has the best support center I have ever seen, their Code Central really rocks and its fill with hundredths' of samples. One of them is is

How to implement the MemberLevel security manually (for example, to deny the 'Read' access for declared properties of some business class, and allow access for the inherited properties

eXpand has the above example as a module since its version 9 and you can use it by using the Xpand.ExpressApp.MemberLevelSecurity.dll assembly following the standard procedure for registering a xaf module.

But in v10 we have boost it a little bit and we have make it conditional so now you can apply multiple Member Access Permissions to a member

image

and by using the criteria member you can force the permission to be applied only to objects that fit those criteria

image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Monday, September 13, 2010

Non constant attributes parameters?

Given my previous post

Simple maths can boost your app performance

did some more thoughts over it in this post 

.Net compiler says no!!

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type   

public class CustomAttribute:Attribute {

    public CriteriaOperator CriteriaOperator { get; set; }

 

    public CustomAttribute(CriteriaOperator criteriaOperator) {

        CriteriaOperator = criteriaOperator;

    }

}

[CustomAttribute(CriteriaOperator.Parse("Name=?","eXpand"))]

public class Class1 {

 

}

the above cannot be compiled

BUT XAF SAYS YES

Why? Cause it has its own type system the XafTypesInfo system. And the types are added it to it at runtime. Meaning? We can do anything!!!

Take for example the following implementation of the above

core classes

public class MyController:ViewController {

    public override void CustomizeTypesInfo(ITypesInfo typesInfo)

    {

        base.CustomizeTypesInfo(typesInfo);

        var typeInfos = XafTypesInfo.Instance.FindTypeInfo(typeof(AttributeRegistrator)).Descendants.Where(info => !(info.IsAbstract));

        foreach (var typeInfo in typeInfos) {

            var logicRegistrator = (AttributeRegistrator)ReflectionHelper.CreateObject(typeInfo.Type);

            foreach (var attribute in logicRegistrator.GetAttributes(typeInfo)) {

                typeInfo.AddAttribute(attribute);

            }

        }

    }

}

 

public abstract class AttributeRegistrator {

    public abstract IEnumerable<Attribute> GetAttributes(ITypeInfo typesInfo);

}

implemention

public class CustomAttributeRegistrator:AttributeRegistrator {

    public override IEnumerable<Attribute> GetAttributes(ITypeInfo typesInfo) {

        if (typesInfo==typeof(Class1))

            yield return new CustomAttribute(CriteriaOperator.Parse("Name=?", "eXpand"))

    }

}

Cause modern programming is based on attributes the AttributeRegistrator example is most usefull when for example multiple developers wan to to work on the same class, the example was stolen from eXpand featurecenter application were that case is valid :) (Many developers work on the same file)

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Wednesday, September 8, 2010

ERP to XAF connection on the fly part1

There is a new kid on the block called DBMapper that obsoletes SqlDBMapper. DBMapper has the same functionality as SqlDbMapper however is based on the powerful XPO . Thus  DBMapper module is capable of transforming into WorldCreator persistent classes the following list of databases: Access, AdvantageAdaptive Server Anywhere, Ase, DB2FireBirdFireBirdSqlSqlServerCeSqlServerODP
OraclePersasizeSqlPostgreSqlSQLiteVistaDB
Some years ago (before Xaf was born) you have bought an ERP for your company and you are not satisfied with its Analysis,Reporting,PIvoting,Sceduling etv capabilities and you wish the creator of your ERP to have use Xaf instead.
If you are looking for the easiest way to map your ERP database into a Xaf application expand framework has the solution for you its called WorldCreator SqlDBMapper module. That module can map any Sql server database into a Xaf application. Bellow I demo how you can use it.
Create an empty eXpand solution
image
or use an existing one and navigate to the persistent assembly listview
image
create a new persistent assembly info object, for the sake of the demo i will map NorthWind database,
image
Use the Tools/Map Database action
image
to connect to a database
image
assign the default navigation path where your the generated classes want to appear in the navigation menu
image
The above actions will generate persistent classes that will map the exact schema of any sql database (all relations/types are supported)
It will also produce the code of the classes and you may copy it and add it to your solution and not use the runtime version of them
image
After restarting the application eXpand will compile that code and load it as Xaf module , It will also connect to the database allowing you to modify/analyze its data. Also an assembly will be created at the application directory for further use with the name NorthWind.expand
Final the navigation items in the path you set above (WorldCreator/NorthWind)
image
and you are ready !!!

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Monday, September 6, 2010

Simple maths can boost your app performance

Xaf provides methods in your controllers to enable you to customize the types that is using. I am speaking about the CustomizeTypesInfo method

internal class MyClass:ViewController {

    public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo)

    {

        base.CustomizeTypesInfo(typesInfo);

    }

}

The thing is that using such decoupled approach can be very dangerous and resource consuming.

Take the following example .

Say you have 10 classes and you want to customize 2 of them . You also want to decouple the customization logic.

Then you probably write one controller like

internal class MyController1:ViewController {

    public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo)

    {

        base.CustomizeTypesInfo(typesInfo);

        var type = typeof(Class1);

        foreach (var typeInfo in typesInfo.PersistentTypes.Where(info => info.Type==type)) {

            typeInfo.AddAttribute(new SomeAttribute());

        }

    }

}

and another one like

internal class MyController2:ViewController {

    public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo)

    {

        base.CustomizeTypesInfo(typesInfo);

        var type = typeof(Class2);

        foreach (var typeInfo in typesInfo.PersistentTypes.Where(info => info.Type==type)) {

            typeInfo.CreateMember("SomeName", typeof (SomeType));

        }

    }

}

the decoupling you wanted has as result to force the CLR to enumerate your typesInfo.PersistentTypes twice in order to apply your logic. And if you put that in real world your classes may be 500 and your logics 1000 that means 500x500 to apply 1000 logics!!! Its a big number and can slow you down for sure

Luckily that Xaf architecture can help us once more here!!! And to those that guess it already i am again speaking about the powerfull XafTypesInfo system.

So how to design the above to get max performance?

1st create 2abstract classes like

public abstract class LogicRegistrator {

    protected abstract void ExecuteCore(ITypeInfo typeInfo);

    public abstract void Execute(ITypeInfo typeInfo);

 

}

public abstract class LogicRegistrator<T> : LogicRegistrator

{

    public override void Execute(ITypeInfo typeInfo)

    {

        if (typeInfo.Type == typeof(T))

            ExecuteCore(typeInfo);

    }

}

then create 2 more classes for implementing your logics

public class Behaviour1:LogicRegistrator<Class1> {

    protected override void ExecuteCore(ITypeInfo typeInfo) {

        typeInfo.AddAttribute(new SomeAttribute());

    }

}

public class Behaviour2:LogicRegistrator<Class2> {

    protected override void ExecuteCore(ITypeInfo typeInfo) {

        typeInfo.CreateMember("SomeName", typeof(SomeType));

    }

}

and final step one controller that can handle all logics.

internal class MyController:ViewController {

    public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo)

    {

        base.CustomizeTypesInfo(typesInfo);

        var typeInfos = XafTypesInfo.Instance.FindTypeInfo(typeof(LogicRegistrator)).Descendants.Where(info => !(info.IsAbstract));

        foreach (var typeInfo in typeInfos) {

            var logicRegistrator = (LogicRegistrator) ReflectionHelper.CreateObject(typeInfo.Type);

            logicRegistrator.Execute(typeInfo);

        }

    }

}

That way your logic still remain decoupled at LogicRegistrator descenants and you not have to enumarate all persistent classes for each one of them.

ps: I did not calculate how much faster that would be cause the post was about simple maths :)

To be continued….

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Wednesday, September 1, 2010

Custom controls everywhere

eXpand have AdditionalViewControlsProvider module that has been design to allow you to add custom controls on a predefined position (Bottom,Top) using its logic architecture ruling system

image

image

image

We wanted to add some power to it so in eXpand v10 one is able to position its custom controls any where in the view by setting the rule position to DetailViewItem

image

Then use the Model editor to create an additionalviewcontrol detailview item

image

Associate them with a rule like

image

and finally use the Layout Designer to place them at any position in the View!!!

image

so when you go to the specified view since your rules can be activated uppon any logic your controls visibility will be setup accordingly

image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!