Blogs

Gary's Blog

January 2009 - Posts

  • XAF and XPO in the Real World

         

    To some, it may seem that, as we evangelists sit here writing about DX products, we are in somewhat of an ivory tower; insulated somehow from the rigors of the real world. However, it is not like that for our customers. Our customers are out there, day after day, putting the theory that we evangelists preach into practice. One such customer is Freelander.

    Freelander has been developing innovative and effective IT applications since 2002. All their developments are noted for their high quality, guaranteeing maximum IT added-value and performance for their customers. They also offer an XAF consultancy service so that they can share with their clients the knowledge and experience they have acquired whilst developing applications in XAF.

    You can read more on how Freelander uses XAF on this page of their site. Well done guys, keep up the good work!

    Technorati tags: , , ,

    Digg This
  • XPO, What’s Coming in 2009?

         

    If you’ve been following some of the other blog posts on the DX site recently, you will be aware that we are currently planning our 9.X release cycle. So what can you expect as an XPO customer? Well this year we have decided to pay a lot more attention to XPO. Last year some of our customers, along with some of us here at Developer Express, felt that XPO had been neglected; this year we intend to rectify this. How will we rectify this? Well we’ve listened to our customers and we’ve come up with a lot of great features that will be introduced throughout the 9.X cycle.

    These features include (in no significant order):

    Persistent Interfaces
    This will enable an XPO user to retrieve objects by specifying an interface. This will retrieve a group of objects, that might be of a different type, but that implement the desired interface.

    Asynchronous Data Loading
    The XPO team will introduce asynchronous data loading to XPO. Developer Express feels that Silverlight is an upcoming and important developer platform upon which XPO can deliver great benefits. This is one of two features DX are adding to XPO in order to support customers who are moving onto this platform.

    In memory Data Store
    The second feature we are adding to XPO to support our customer’s move onto the Silverlight platform, is a new in memory data store which will not be based on the DataSet.  This will negate Siliverlight’s lack of support for datasets and will use less memory, thus making it more performant.

    DateTime Operations
    As you’ll know different RDBMS handle dates, and date parts (day, week month, etc), in differing ways. The XPO team will introduce an abstraction layer which will allow you to handle dates in a uniform manor regardless of the underlying supported RDBMS.

    Provider Independent Data Definition Language
    The data definition language differs across each RDBMS we support. The XPO team will introduce a layer that will allow abstracted schema updates regardless of which supported RDBMS you are using.

    ADO.net Data Services
    During the 9.X release cycle the  XPO team will introduce support for ADO.Net Data Services, for more information on this technology, visit the ADO.Net web site.

    Am sure you’ll agree with me that these are a great set of features, but the good news doesn’t stop there! XPO has had a new resource allocation, and we have a lot of great ideas. This means that, hopefully, we’ll be able to deliver even more features for XPO in the coming year. For example, we are planning great things like multi-tier support, both in and outside of Silverlight, though the plans aren't quite concrete enough to be included here explicitly.

    As always we’ll be continuing to solicit your feed back via the forums and blog post comments, so please continue to engage with us throughout the 9.X cycle and together we’ll make XPO into the successful product we all want it to be.

  • XAF, What’s Coming in 2009?

         

    As you’ll have noticed by now, there are a few of us Developer Express types sequestered away in a nice hotel in Vegas, thrashing out what what we are going to deliver to our customers in 2009.

    So what can you expect as an XAF customer? Well XAF continues to be an important strategic platform for Developer Express, one on which we intend to make an big investment during 2009. Currently we are restructuring the team in order to better service our customer’s requirements.

    Due to this team restructuring, and because we are aware of the fact that, historically, we have disappointed our customers with previous unmet promises, this year we are being cautious with what we announce. Having said that, the first thing we are going to announce for 9.1 (which will be available soon) should put a big smile on the faces of our customers, and that’s because it’s the action you most want us to take.

    For 9.1 we are going to be concentrating on many of the outstanding TBD issues.  For more information on this, check out Julian’s blog posting. As I said this action has been the most requested in the forums and in private conversations I’ve had, and it’s great that we can achieve this in the first release of 2009!

    As for what is coming after 9.1 well, during the course of the 9.X release cycle, XAF customers can look forward to:

    • Improvements in performance both in terms of start up time and in terms of multi user web applications.
    • Improvements in usability both for the developer and for the end user.
    • Localisation the team will be looking at ways to make XAF compatible with third party localisation tools.
    • Over the course of the cycle we’ll be looking to improve our documentation set for XAF as well as increasing the number of our samples that are written in Visual Basic.

    To add to this, the team will be evaluating technologies such as WPF and Silverlight with a view to having a prototype of XAF utilising these technologies by the end of the year.

    The final thing I want to announce in this post is the immediate setting up of a Framework Advisory Board. There will be a future post on the subject of this board, but for now let me just say this board shows the continuing and long term commitment that we have for listening to, and acting upon, the views of our customers.

    As I said at the top of this post, we are being cautious with what we are promising in the 9.X cycle. Customers should not take that to mean that we are not committed to XAF (we most certainly are) and we look forward to being able to deliver more of the outstanding feature promises, than we have documented here, over the next release cycle.

    Going forward we will continue to solicit feedback on XAF via the forums and the new Framework Advisory Board. So I hope you agree with me that there is a lot to look forward to in the coming year!

  • XAF – Cloning Objects #2

         

    In a previous post, on cloning objects in XAF, I showed you how to use the Clone Module. Of course, this solution only works if there is user interaction. What if you want to do this programmatically? Well, given the following business class:

    using System;
    using DevExpress.Xpo;
    
    namespace SimpleObject {
        public class Parent : XPObject {
            public Parent(Session session) : base(session) { }
            public override void AfterConstruction() {
                base.AfterConstruction();
            }
    
            private string _Name;
            public string Name {
                get {
                    return _Name;
                }
                set {
                    SetPropertyValue("Name", ref _Name, value);
                }
            }
    
            [Association("ParentChildren"), Aggregated]
            public XPCollection<Child> Children {
                get { return GetCollection<Child>("Children"); }
            }
        }
    
        public class Child : XPObject {
            public Child(Session session) : base(session) { }
            public override void AfterConstruction() {
                base.AfterConstruction();
            }
    
            private string _Name;
            public string Name {
                get {
                    return _Name;
                }
                set {
                    SetPropertyValue("Name", ref _Name, value);
                }
            }
    
            private Parent _Parent;
            [Association("ParentChildren")]
            public Parent Parent {
                get {
                    return _Parent;
                }
                set {
                    SetPropertyValue("Parent", ref _Parent, value);
                }
            }
        }
    }

    And the following helper class:

    using System;
    using DevExpress.Xpo;
    using System.Collections.Generic;
    using DevExpress.Xpo.Metadata;
    using System.Collections;
    
    namespace SimpleObject {
        public class CloneIXPSimpleObjectHelper {
            /// <summary>
            /// A dictionary containing objects from the source session as key and objects from the 
            /// target session as values
            /// </summary>
            /// <returns></returns>
            Dictionary<object, object> clonedObjects;
            Session sourceSession;
            Session targetSession;
    
            /// <summary>
            /// Initializes a new instance of the CloneIXPSimpleObjectHelper class.
            /// </summary>
            public CloneIXPSimpleObjectHelper(Session source, Session target) {
                this.clonedObjects = new Dictionary<object, object>();
                this.sourceSession = source;
                this.targetSession = target;
            }
    
            public T Clone<T>(T source) where T : IXPSimpleObject {
                return Clone<T>(source, targetSession, false);
            }
            public T Clone<T>(T source, bool synchronize) where T : IXPSimpleObject {
                return (T)Clone(source as IXPSimpleObject, targetSession, synchronize);
            }
    
            public object Clone(IXPSimpleObject source) {
                return Clone(source, targetSession, false);
            }
            public object Clone(IXPSimpleObject source, bool synchronize) {
                return Clone(source, targetSession, synchronize);
            }
    
            public T Clone<T>(T source, Session targetSession, bool synchronize) where T : IXPSimpleObject {
                return (T)Clone(source as IXPSimpleObject, targetSession, synchronize);
            }
    
            /// <summary>
            /// Clones and / or synchronizes the given IXPSimpleObject.
            /// </summary>
            /// <param name="source"></param>
            /// <param name="targetSession"></param>
            /// <param name="synchronize">If set to true, reference properties are only cloned in case
            /// the reference object does not exist in the targetsession. Otherwise the exising object will be
            /// reused and synchronized with the source. Set this property to false when knowing at forehand 
            /// that the targetSession will not contain any of the objects of the source.</param>
            /// <returns></returns>
            public object Clone(IXPSimpleObject source, Session targetSession, bool synchronize) {
                if (source == null)
                    return null;
                if (clonedObjects.ContainsKey(source))
                    return clonedObjects[source];
                XPClassInfo targetClassInfo = targetSession.GetClassInfo(source.GetType());
                object clone = null;
                if (synchronize)
                    clone = targetSession.GetObjectByKey(targetClassInfo, source.Session.GetKeyValue(source));
                if (clone == null)
                    clone = targetClassInfo.CreateNewObject(targetSession);
                clonedObjects.Add(source, clone);
    
                foreach (XPMemberInfo m in targetClassInfo.PersistentProperties) {
                    if (m is DevExpress.Xpo.Metadata.Helpers.ServiceField || m.IsKey)
                        continue;
                    object val;
                    if (m.ReferenceType != null) {
                        object createdByClone = m.GetValue(clone);
                        if ((createdByClone != null) && synchronize == false)
                            val = createdByClone;
                        else {
                            val = Clone((IXPSimpleObject)m.GetValue(source), targetSession, synchronize);
                        }
    
                    }
                    else {
                        val = m.GetValue(source);
                    }
                    m.SetValue(clone, val);
                }
                foreach (XPMemberInfo m in targetClassInfo.CollectionProperties) {
                    if (m.HasAttribute(typeof(AggregatedAttribute))) {
                        XPBaseCollection col = (XPBaseCollection)m.GetValue(clone);
                        XPBaseCollection colSource = (XPBaseCollection)m.GetValue(source);
                        foreach (IXPSimpleObject obj in new ArrayList(colSource))
                            col.BaseAdd(Clone(obj, targetSession, synchronize));
                    }
                }
                return clone;
            }
        }
    }

    Then cloning can be performed using the following code:

    private void Form1_Load(object sender, System.EventArgs e) {
         UnitOfWork uow1 = new UnitOfWork();
         Parent obj = new Parent(uow1);
         obj.Name = "Parent A";
         Child ch1 = new Child(uow1);
         ch1.Name = "Child 1";
    
         Child ch2 = new Child(uow1);
         ch2.Name = "Child 2";
    
         obj.Children.Add(ch1);
         obj.Children.Add(ch2);
         obj.Save();
         uow1.CommitChanges();
    
         listBox1.Items.Add(string.Format("Object created: {0}", obj.Name));
    
         UnitOfWork uow2 = new UnitOfWork();
         CloneIXPSimpleObjectHelper cloneHelper = new CloneIXPSimpleObjectHelper(uow1, uow2);
         Parent clone = cloneHelper.Clone(obj) as Parent;
    
         listBox1.Items.Add(string.Format("Object cloned: {0}", clone.Name));
         listBox1.Items.Add(string.Format("Object's child 1: {0}", clone.Children[0].Name));
         listBox1.Items.Add(string.Format("Object's child 2: {0}", clone.Children[1].Name));
     }
    Digg This
  • XAF – Cloning Objects #1

         

    Hanging out in the DX forums, as I do, you can pick up on some interesting scenarios that our customers come across. Today we had a bit of a discussion on object cloning in XAF and I I thought the topic sufficiently interesting to surface here for general consumption.

    So what is object cloning then. Well, briefly, image that an object is “expensive” to create (perhaps you have to make a number of queries to a few different database systems to create this object). Now imagine that you want to create a second object, it is almost identical to the first (expensive to create) object, but differs in that values in a few, minor, properties are different. Now, instead of going through the “expensive” process a second time to create this other object, you can simply clone the first object and change those properties, programmatically, after creation.

    Of course, XAF has built in support for object cloning via the Clone Module. The Clone Module consists of a single assembly: DevExpress.ExpressApp.CloneObject.vX.X, which you can add to the common application module, in both Windows Forms and ASP.NET Web applications,to gain access to its CloneObject Action. The Clone Object module supplies the CloneObject View Controller. This Controller contains the CloneObject Single Choice Action, targeted for cloning the currently selected object. In addition, the CloneObject module extends the Application Model's Application | BOModel| Class node with the IsClonable attribute. Set this attribute to true to enable cloning of this class' objects.

    The CloneObject Action is activated for the Views that represent the object type whose IsClonable attribute is set to true. This Action enables you to create a clone of the current object. In addition, you can create an object of the class which is inherited from the current object's base class. For this purpose, set the base class's IsClonable attribute to true. The following image demonstrates the CloneObject Action activated for the Contact class. The Action's dropdown list contains the Contact and User types because the IsClonable attribute is set to true for the Person class - the base class for both Contact and User.

    Of course, the Clone Module can be customized. To edit the settings of the CloneObjectController or the CloneObject Action, use the Application Model's Application | ActionDesign | Actions | Action or Application | ActionDesign Node | Controllers | Controller nodes. To change the behavior of the CloneObjectController or CloneObjectAction, create a custom View Controller, and access the Controller and its Action in the Controller.Activated event handler. The following code demonstrates how to prohibit adding descendant types of the current object type's base type to the Clone Action's Items collection:

    using DevExpress.ExpressApp.CloneObject;
    //...
    public partial class MyCloneObjectController : ViewController {
       //...
       private void MyCloneObjectController_Activated(object sender, EventArgs e) {
          CloneObjectViewController cloneObjectController = Frame.GetController();
          cloneObjectController.CloneObjectAction.Items.Clear();
          ChoiceActionItem myItem = 
             new ChoiceActionItem(Application.FindClassInfo(View.ObjectType), View.ObjectType);
          cloneObjectController.CloneObjectAction.Items.Add(myItem);
       }
    }

    Digg This
More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.