eXpand Framework calculated members creation—Pros and Cons

XAF Team Blog
20 September 2011

Let me describe for a moment how we at DevExpress work. We build and sell software which means that we only sell and provide support for products that have been built and tested by us! However I am here as a framework evangelist and huge XAF fan. This makes it my duty to spread the word as much as I can and make XAF even bigger. To this end through collaboration within the XAF community, we have been building and supporting eXpand. This framework follows XAF to the letter and takes things even further. eXpand gets its inspiration from real life situations and bases itself on examples from DevExpress Support Center. eXpand is the first open source project based on the DevExpress eXpressApp Framework (XAF). More info is available at www.expandframework.com and our very existence relies on your efforts! Anyone is welcome to contribute and enjoy the rewards. It is not necessary to be a XAF guru, we can all manage to create a behavior taken from DevExpress code central. Let’s work together to enhance our beloved XAF!

As promised in the previous post I will now attempt to provide a concise yet comprehensive look at the 5 possibilities that Xpand gives us when we want to create a calculated member. I will also provide discussion of the relative advantages and disadvantages of each approach. We can see all of them in action in Xpand FeatureCenter application. Remember it is only thanks to the fact that XAF/XPO have such a strong and flexible architecture that this is possible! We must also acknowledge that these approaches have evolved as a direct result of contributions from the XAF team and community.

image

1. The XPO way –>Using Code

Take a look at the CreateCalculabeMember extension method in the code below,

public class CreateRuntimeCalculatedFieldController : ViewController {

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

        base.CustomizeTypesInfo(typesInfo);

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

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

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

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

            typesInfo.RefreshInfo(typeof(Customer));

        }

    }

}

 

XPO has a dictionary of domain metadata. The metadata of each persistent object is stored in XPClassInfo classes and the metadata of their properties is stored in XPMemberInfo classes. One of the main advantages of this approach is that it  adds a new member to the XPO dictionary and therefore follows XAF to the letter. This is because in order to form the model XAF first queries the XPO dictionary and finally in order to configure the views it queries the model. Since we have worked in the data layer our calculated values will be sent to any data bound enabled control for rendering. The other benefit is that if we code there are no restrictions on what we can do, for example we can create members calling a WCF service. The sky’s the limit!

On the other hand each time we write new code we need to spend time testing and distributing it. Furthermore in certain scenarios problems can occur due to the fact that we add a new member to the object. For each new member we add to an object we are forced to deal with long properties lists in our model which can be somewhat unwieldy – imagine an  object with 200 properties.

Note; XAF is smart enough to manage all of this without even breaking a sweat. This means that its performance does not suffer in any way. It is simply that this approach can leave the user with a bit of a headache!

2. Using the model

We have extended our model in order to describe all types of calculated and runtime properties.

 

image_thumb[14]

 

Having done this makes it pretty easy to utilize the powerful XPO and add members in its dictionary as with the previous approach. This means this method shares some of the benefits we mentioned above. However as we are not writing code we can’t enjoy the same level of flexibility unless we utilize ModelUpdaters. Also as the columns can only be created using model editor they are only useful in situations when we have permission to modify the model. Finally we could end up with a huge number of properties here too for the same reason we identified previously.

 

All this is not to say that this approach doesn’t have its own unique advantages. For example the model difference can be stored in a database or xml file making it easy to distribute. To this end we can use the build in API or a specialized module like IO. Moreover it is possible to develop on site (client). Of course working at the model level allows us to use a model manager module like ModelDifference which is a great aid. It can be used to distribute the unbound columns to users, roles and even to other applications. In addition since ModelDifference supports both platforms it is possible to create calculated members without restarting the application or IIS.

3.WorldCreator extended members

This module maps the structure of the XPMemberInfo class to a persistent object. This approach is again similar to model approach (and once again has similar benefits) however there is a crucial difference. Instead of using the model to gather data to form the calculated members we use the input taken from the UI.

image_thumb[17]image_thumb[20]

Using the UI is simplicity itself! It requires no technical knowledge whatsoever as the user is only required to choose from a set of basic options. We can still code if we wish, this time by creating persistent objects and then leaving eXpand to take care of the rest. That being said the real beauty of this approach is that the product can be developed on site without the user having to write a single line of code or using a sophisticated tool like Model Editor. Moreover we can enjoy ease of distribution due to the fact that our objects are stored in the database. As the metadata is now in the form of persistent objects locating it and working with it is as easy as ever.

By now it should be clear that as we are still relying on XPO we are faced with the same old problem regarding multiple views.

4. Using a WordCreator Dynamic Assembly

Our fourth approach uses the same module to create dynamic persistent assemblies using code generation templates. XAF is the best framework to describe domains which is evidenced by the way that  WorldCreator maps the Assembly structure to persistent objects and auto generates a flexible UI.

image_thumb[23]

Using the templates will create a dynamic assembly with exactly the same code and structure as if we had taken the time to design it ourselves inside VS. Distribution is still easy since is everything is in the database. The fact that we script at runtime means that our options are almost unlimited when taking this approach.

5. The Unbound Column

Extending the model with an Unbound column node as shown makes it possible to create Unbound grid columns and set their unbound expressions.

image

 

image

This is the only approach that allows us to work directly on views without utilizing XPO. This means that we gain the maximum level of flexibility since it is possible to have different columns for the same object views. Therefore we can work on this column independently. At the same time the end user can change the UnboundExpression at runtime using expression editor (windows only). When it comes to distribution we find the same advantages as we do whenever we deal with the model.

As with the second approach we lose some flexibility because we are not writing code but again we can get round this using ModelUpdaters. In addition our columns still cannot be used when we do not have permission to modify the model. Another disadvantage concerns the fact that XAF is designed to make all calculations in the data layer and send the values to controls by applying an MVC pattern. A few years after XAF was released, Microsoft built Silverlight featuring very similar architecture. Taking into account the various factors this has been recognized as the optimal approach. Although using Unbound columns allows us to work in a different way we need to write extra code to support each control (Tree, Pivot etc) because the calculations are performed in the UI.


We are happy to read your feedback about this!. Remember that your questions are the best candidates for future posts.

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.