Saturday, June 19, 2010

MMV Lib now available at CodePlex



The Multiuse-Model View examples from my previous posts can now be found in one complete project at codeplex: mmv.codeplex.com. Enjoy!



Wednesday, May 19, 2010

MultiuseModel-View (MMV) Object modeling pattern with WPF and WCF: Wrapping it up



In my previous articles, I described how to create an ObservableObject to wrap notification functionality, a DatabaseObject to wrap calls to the DB, and a CommunicationObject to wrap client-server communication code. In this brief article I will describe how to wrap it all together under one common API.



The MultiuseObject<T>


The purpose of this class is very simple: to make the appropiate API call depending on where the code is executing. In other words, when calling the Save method, we want a smart object to send it over the wire to the server if the code is executing on the client or call the ORM layer to persist the data into the database if the code is executing on the server. To accomplish this we first need to provide the library info regarding where the code is executing. We start by defining an enum with the possible choices:


public enum ServiceType
{
 Client = 0,
 WebServer = 1,
 AppServer = 2
}

And then we define a utility class to extract the values from the config file:


internal sealed class CommunicationConfiguration
{
 private static object _SynchLock = new object();
        private static CommunicationConfiguration _Current;
        public static CommunicationConfiguration Current
        {
            get
            {
                if (_Current == null)
                {
                    lock (_SynchLock)
                    {
                        _Current = new CommunicationConfiguration();
                    }
                }
                return (_Current);
            }
        }

        private ServiceType? _CurrentServiceType;
        public ServiceType CurrentServiceType
        {
            get
            {
                if (ConfigurationManager.AppSettings["ServiceType"] == null)
                    throw new InvalidConfigurationException(string.Format("ServiceType is a required Application Setting. Acceptable values are: {0}", string.Join(", ", Enum.GetNames(typeof(ServiceType)))));
                if (_CurrentServiceType == null)
                    _CurrentServiceType = (ServiceType)Enum.Parse(typeof(ServiceType), ConfigurationManager.AppSettings["ServiceType"]);
                return (_CurrentServiceType.Value);
            }
        }

        private CommunicationConfiguration()
        {
        }
    }
}

Now all we need to do is ensure that the applications using the library define appropiate configuration values:


<appSettings>
<add key="ServiceType" value="Client"/>
</appSettings>

The only thing left here is to create a class that inherits CommunicationObject<T> and uses the configuration to determine which call it should make:


public abstract class MultiuseObject<T> : CommunicationObject<T>
{
        public void Load(object primaryKeyValue)
        {
            if (CommunicationConfiguration.Current.CurrentServiceType == CommunicationConfiguration.ServiceType.Client)
                LoadFromServer(primaryKeyValue);
            else if (CommunicationConfiguration.Current.CurrentServiceType == CommunicationConfiguration.ServiceType.WebServer)
                LoadFromServer(primaryKeyValue);
            else if (CommunicationConfiguration.Current.CurrentServiceType == CommunicationConfiguration.ServiceType.AppServer)
                LoadFromDB(primaryKeyValue);
        }

        public void Save()
        {
            if (CommunicationConfiguration.Current.CurrentServiceType == CommunicationConfiguration.ServiceType.Client)
                SaveToServer();
            else if (CommunicationConfiguration.Current.CurrentServiceType == CommunicationConfiguration.ServiceType.WebServer)
                SaveToServer();
            else if (CommunicationConfiguration.Current.CurrentServiceType == CommunicationConfiguration.ServiceType.AppServer)
                SaveToDB();
        }
}

In a nutshell, this is all there is to building a robust object modeling library!


Note: I did not include source code files for these classes because I will be packaging up all the sample files into a codeplex project. Stay tuned!!





Sunday, April 4, 2010

MultiuseModel-View (MMV) Object modeling pattern with WPF and WCF: The Other Side



Download sample CommunicationObject File
Download sample ICommunicationServiceContract File
Download sample CommunicationCollectionEx File
Download sample CommunicationService File
Download sample ServiceClient File
Download sample NetDataContractSerializerBehavior File
Download sample NetDataContractSerializerElement File
Download sample NetDataContractSerializerOperationBehavior File



In my previous articles, I described how to create a DatabaseObject<T> that allows the inheritors to maintain a persistent state on a database. In this article I will show you how to create an object that sends itself across the wire from and to the client using WCF.



Fore note


Because of the complexity involved in serializing objects and sending them through the wire between servers or between a server and a client, we cannot simply wrap all the functionality into one class. Instead we'll have to create several classes that work together under the umbrella of a "facade" class (our CommunicationObject<T>). Moreover, much like the database functionality provided by DatabaseObject<T> and DatabaseCollectionEx, we'll have to provide both single instance and collection implementations of our communication classes.



The CommunicationObject<T> Class



The CommunicationObject<T> is a very simple class, since by itself it doesn't do much other than relying on other classes to send itself to or get itself from the server. Much like the DatabaseObject<T>, the CommunicationObject<T> provides only two methods: LoadFromServer and SaveToServer.


public abstract class CommunicationObject : DatabaseObject
{
    public void LoadFromServer(object primaryKeyValue)
    {
        ServiceClient client = new ServiceClient();
        object loaded = client.ContractChannel.LoadObject(typeof(T), primaryKeyValue);
        foreach (PropertyInfo pi in typeof(T).GetProperties())
            pi.SetValue(this, pi.GetValue(loaded, null), null);
    }

    public void SaveToServer()
    {
        ServiceClient client = new ServiceClient();
        // We call CreateOverridenType first to ensure that the server has loaded the extended type of T on the dynamic assembly.
        // Failure to do so would result in a CommunicationException because the deserializer would not be able to find the type.
        client.ContractChannel.CreateOverridenType(typeof(T));

        object reloaded = client.ContractChannel.SaveObject(this);
        foreach (PropertyInfo pi in typeof(T).GetProperties())
            pi.SetValue(this, pi.GetValue(reloaded, null), null);
    }
}

What's important to note here is that these methods themselves are the ones who instantiate a service client. In other words, we are wrapping the functionality that typically lives elsewhere in our applications and usually is spread around in multiple places into just one class that any of the business objects can inherit from. Other than that, the CommunicationObject ensures that the object instance properties are updated every time an object is loaded or saved.


The ServiceClient uses the ICommunicationService interface as its contract. The ICommunicationService interface defines methods for both single instance objects as well as collections and it also offers the ability for the caller to create an overridden type remotely (this is important to ensure that both the client and the server have the same types loaded).


[ServiceContract]
public interface ICommunicationServiceContract
{
    // CommunicationObject Methods

    [OperationContract]
    void CreateOverridenType(Type databaseObjectType);

    [OperationContract]
    object LoadObject(Type databaseObjectType, object primaryKeyValue);

    [OperationContract]
    object SaveObject(object objectToSave);

    // CommunciationCollection Methods

    [OperationContract]
    object LoadCollection(Type databaseObjectType);

    [OperationContract]
    object LoadCollectionWithCriteria(Type databaseObjectType, ICriterion[] criteria);

    [OperationContract]
    object SaveCollection(object collectionToSave);

}


CommunicationCollectionEx


Thanks to extension methods in .Net 3.5 we don't have to create our own collection class to extend the functionality of each type of collection (List, Dictionary, etc). Instead we can just use a bunch of extension methods that operate on ICollection<T> to provide the functionality we want.


public static class CommunicationCollectionEx
{
    public static void LoadFromServer(this ICollection collection)
    {
        // we ensure that the returning objects have a corresponding type loaded.
        ObservableObject.CreateOverridenType();

        ServiceClient client = new ServiceClient();
        object loaded = client.ContractChannel.LoadCollection(typeof(T));
        foreach (T item in (ICollection)loaded)
            collection.Add(item);
    }

    public static void LoadFromServer(this ICollection collection, params ICriterion[] criteria)
    {
        // we ensure that the returning objects have a corresponding type loaded.
        ObservableObject.CreateOverridenType();

        ServiceClient client = new ServiceClient();
        object loaded = client.ContractChannel.LoadCollectionWithCriteria(typeof(T), criteria);
        foreach (T item in (ICollection)loaded)
            collection.Add(item);
    }

    public static void SaveToServer(this ICollection collection)
    {
        // we ensure that the returning objects have a corresponding type loaded.
        ObservableObject.CreateOverridenType();

        ServiceClient client = new ServiceClient();
        // We also ensure that the object has been overriden on the server as well.
        client.ContractChannel.CreateOverridenType(typeof(T));
        object loaded = client.ContractChannel.SaveCollection(collection);
        collection.Clear();
        foreach (T item in (ICollection)loaded)
            collection.Add(item);
    }
}

As you can see, there are also two basic methods (one is overloaded) defined in this class: LoadFromServer and SaveToServer. Much like their single-instance counterparts, these methods create an instance of SeviceClient to call the appropriate operations defined by ICommunicationServiceContract. The overloaded LoadFromDatabase object also allows for defining a set of criteria to reduce the resultset.



Implementing CommunicationService


Previously I talked about the ICommunicationServiceContract as the provider of functionality to get and save objects across the wire. This interface needs an implementation, and for reusability purposes we want to define it as part of our core classes.


public class CommunicationService : ICommunicationServiceContract
{
    public void CreateOverridenType(Type databaseObjectType)
    {
        ObservableObject.CreateOverridenType(databaseObjectType);
    }

    public object LoadObject(Type databaseObjectType, object primaryKeyValue)
    {
        object databaseObject = Activator.CreateInstance(ObservableObject.CreateOverridenType(databaseObjectType));
        databaseObjectType.GetMethod("LoadFromDB").Invoke(databaseObject, new object[] { primaryKeyValue });
        return (databaseObject);
    }

    public object SaveObject(object objectToSave)
    {
        objectToSave.GetType().GetMethod("SaveToDB").Invoke(objectToSave, null);
        return (objectToSave);
    }

    public object LoadCollection(Type databaseObjectType)
    {
        object list = Activator.CreateInstance(typeof(List<>).MakeGenericType(databaseObjectType));
        MethodInfo loadFromDBInfo = (from mi in typeof(DatabaseCollectionEx).GetMethods() where mi.Name == "LoadFromDB" && mi.GetParameters().Length == 1 select mi).First().MakeGenericMethod(databaseObjectType);
        loadFromDBInfo.Invoke(null, new object[] { list }); ;
        return (list);
    }

    public object LoadCollectionWithCriteria(Type databaseObjectType, ICriterion[] criteria)
    {
        object list = Activator.CreateInstance(typeof(List<>).MakeGenericType(databaseObjectType));
        MethodInfo loadFromDBInfo = (from mi in typeof(DatabaseCollectionEx).GetMethods() where mi.Name == "LoadFromDB" && mi.GetParameters().Length == 2 select mi).First().MakeGenericMethod(databaseObjectType);
        loadFromDBInfo.Invoke(null, new object[] { list, criteria }); ;
        return (list);
    }

    public object SaveCollection(object collectionToSave)
    {
        MethodInfo saveToDBInfo = (from mi in typeof(DatabaseCollectionEx).GetMethods() where mi.Name == "SaveToDB" && mi.GetParameters().Length == 1 select mi).First().MakeGenericMethod(collectionToSave.GetType().GetGenericArguments()[0]);
        saveToDBInfo.Invoke(null, new object[] { collectionToSave }); ;
        return (collectionToSave);
    }
}

There isn't much of a mystery about this class. It is fairly simple. By using reflection we invoke the appropiate DatabaseObject<T> or DatabaseCollectionEx method to get or save data to the database.



Helper Classes


There are a number of supporting classes that we need to make the classes described above work properly with WCF. The first one being the ServiceClient class we used in our CommunicationObject and CommunicationCollectionEx classes. This class is very simple since all it does is extend the System.ServiceModel.ClientBase class and provides a public accessor to the Channel casted to ICommunicationServiceContract.


internal sealed class ServiceClient : System.ServiceModel.ClientBase where T : class
{
    public T ContractChannel
    {
        get { return ((T)Channel); }
    }

    public ServiceClient()
    {
    }

    public ServiceClient(string endpointConfigurationName) :
        base(endpointConfigurationName)
    {
    }

    public ServiceClient(string endpointConfigurationName, string remoteAddress) :
        base(endpointConfigurationName, remoteAddress)
    {
    }

    public ServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) :
        base(endpointConfigurationName, remoteAddress)
    {
    }

    public ServiceClient(Binding binding, EndpointAddress remoteAddress) :
        base(binding, remoteAddress)
    {
    }
}

Also, other important helper classes are the NetDataContractSerializerX set of classes. These being the NetDataContractSerializerElement, NetDataContractSerializerBehavior and NetDataContractSerializerOperationBehavior which are in charge of serializing objects using the NetDataContractSerializer instead of the traditional DataContractSerializer.


public class NetDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
    public NetDataContractSerializerOperationBehavior(OperationDescription operationDescription)
        : base(operationDescription)
    {
    }
    public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList knownTypes)
    {
        return new NetDataContractSerializer();
    }
    public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList knownTypes)
    {
        return new NetDataContractSerializer();
    }
}

public class NetDataContractSerializerBehavior : Attribute, IServiceBehavior, IEndpointBehavior
{
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (var endpoint in serviceDescription.Endpoints)
            this.RegisterContract(endpoint);
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
        this.RegisterContract(endpoint);
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    protected void RegisterContract(ServiceEndpoint endpoint)
    {
        foreach (OperationDescription desc in endpoint.Contract.Operations)
        {
            var dcsOperationBehavior = desc.Behaviors.Find();
            if (dcsOperationBehavior != null)
            {
                int idx = desc.Behaviors.IndexOf(dcsOperationBehavior);
                desc.Behaviors.Remove(dcsOperationBehavior);
                desc.Behaviors.Insert(idx, new NetDataContractSerializerOperationBehavior(desc));
            }
        }
    }
}

public class NetDataContractSerializerElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(NetDataContractSerializerBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new NetDataContractSerializerBehavior();
    }
}

With all these things in place, all we need to do is ensure that these assemblies are referenced by both our client and our server projects. If so, calling the "SaveToServer" or "GetFromServer" methods of a class that inherits CommunicationObject<T> should yield the expected results.


In my next article, I'll demonstrate how to extend client-server functionality to allow for multi-tier services and how to put everything together into a nice MultiuseObject<T>.




Monday, February 1, 2010

MultiuseModel-View (MMV) Object modeling pattern with WPF and WCF: Hibernation



Download sample ObservableSet File
Download sample ObservableSetType File
Download sample ObservableCollectionType File
Download sample DatabaseObject File
Download sample DatabaseCollection File
Download sample DatabaseSet File
Download sample DatabaseCollectionEx File



In my previous article I went over how to break up a multiuse object into logical parts. In this article I will talk about how to build an object-oriented data layer using a DatabaseObject and NHibernate.



About NHibernate


NHibernate is an Object-Relational Mapping (ORM) for .NET. I've used it extensively and to be honest it's the best library for manipulating data that I've dealt with by far. There are a few different ways in which you can map a class with NHibernate: using XML files, using Attributes, or using a mapping classes with Fluent Hibernate. Personally I use Attributes since it is the least verbose choice and it is also the easiest to extend.


NHibernate is very powerful when it comes down to mapping collections, however, it is also very particular about how it handles collections internally (specifically speaking, it is particular about the lazy-loading functionality). Out of the box NHibernate lets you only use either IList<T> or ISet<T> for collections, and behind the scenes it creates an instance of a custom type (PersistantGenericBag<T>). For WPF applications using IList or ISet is inconvenient because of the lack of change notifications. Ideally we would like to use ObservableCollection instead.


While you cannot use ObservableCollection<T> by default, NHibernate allows you to define your own custom collection. And that's exactly what we should do: we have to create an ObservableSet<T> (which is a HashSet<T> collection that implements INotifyCollectionChanged) and we have to write two custom classes to play nicely with NHibernate: ObservableCollectionType and ObservableSetType.


public class ObservableSet<T> : HashedSet<T>, ISet<T>, INotifyCollectionChanged
{
 public event NotifyCollectionChangedEventHandler CollectionChanged;

 // WPF requires the list index to be passed back to
 // itself when removing an item from the collection.
 // Sets have no indices, so they are hereby added.
 public int IndexOf(T item) { return addOrder.IndexOf(item); }

 private IList<T> addOrder = new List<T>();

 public override bool Add(T item)
 {
  bool isChanged = base.Add(item);
  if (isChanged)
  {
   addOrder.Add((T)item);
   OnCollectionChanged(NotifyCollectionChangedAction.Add, item);
  }
  return isChanged;
 }

 public override bool Remove(T item)
 {
  // WPF requires the list index to be passed back to itself:
  int index = IndexOf(item);
  bool isChanged = base.Remove(item);
  if (isChanged)
  {
   addOrder.Remove((T)item);
   if (CollectionChanged != null)
    CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, (object)item, index));
  }
  return isChanged;
 }

 public override void Clear()
 {
  base.Clear();
  addOrder.Clear();
  OnCollectionChanged(NotifyCollectionChangedAction.Reset, null);
 }

 /// <summary>
 /// Raises the <see cref="CollectionChanged"/> event to indicate that item(s)
 /// have been added to, or removed from, this collection.
 /// </summary>
 protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, object changedItem)
 {
  if (CollectionChanged != null)
   CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
 }
}

internal class ObservableCollectionType<T> : IUserCollectionType
{
        public bool Contains(object collection, object entity)
        {
            return ((IList<T>)collection).Contains((T)entity);
        }

        public IEnumerable GetElements(object collection)
        {
            return (IEnumerable)collection;
        }

        public object IndexOf(object collection, object entity)
        {
            return ((IList<T>)collection).IndexOf((T)entity);
        }

        public object Instantiate(int anticipatedSize)
        {
            return new ObservableCollection<T>();
        }

        public IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister)
        {
            return new DatabaseCollection<T>(session);
        }

        public object ReplaceElements(object original, object target, ICollectionPersister persister, object owner, IDictionary copyCache, ISessionImplementor session)
        {
            IList<T> result = (IList<T>)target;
            result.Clear();
            foreach (object item in ((IEnumerable)original))
                result.Add((T)item);
            return result;
        }

        public IPersistentCollection Wrap(ISessionImplementor session, object collection)
        {
            return new DatabaseCollection<T>(session, (ObservableCollection<T>)collection);
        }
}

internal class ObservableSetType<T> : IUserCollectionType
{
        public bool Contains(object collection, object entity)
        {
            return ((ISet<T>)collection).Contains((T)entity);
        }

        public IEnumerable GetElements(object collection)
        {
            return (IEnumerable)collection;
        }

        public object IndexOf(object collection, object entity)
        {
            return -1;
        }

        public object Instantiate(int anticipatedSize)
        {
            return new ObservableSet<T>();
        }

        public IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister)
        {
            return new DatabaseSet<T>(session);
        }

        public object ReplaceElements(object original, object target, ICollectionPersister persister, object owner, IDictionary copyCache, ISessionImplementor session)
        {
            ISet<T> result = (ISet<T>)target;
            result.Clear();
            foreach (object item in ((IEnumerable)original))
                result.Add((T)item);
            return result;
        }

        public IPersistentCollection Wrap(ISessionImplementor session, object collection)
        {
            return new DatabaseSet<T>(session, (ObservableSet<T>)collection);
        }
}


The DatabaseObject<T> Class


When using NHibernate, creating a class that could load or save an object is extremely trivial. The implementation of a DatabaseObject<T> class would look something like this:


public abstract class DatabaseObject<T> : ObservableObject<T>
{
        public void Save()
        {
            ISession session = NHibernateHelper.Configuration.BuildSessionFactory().OpenSession();
            session.SaveOrUpdate(this);
            session.Flush();
            session.Close();
        }

        public void Load(object id)
        {
            ISession session = NHibernateHelper.Configuration.BuildSessionFactory().OpenSession();
            T loaded = (T)session.Load(ObservableObject.CreateOverridenType(typeof(T)), id);
            foreach (PropertyInfo pi in typeof(T).GetProperties())
                pi.SetValue(this, pi.GetValue(loaded, null), null);
            session.Flush();
            session.Close();
        }
}

There are a couple of things worthwhile noting about the DatabaseObject<T> class.


First of all, notice that we flush and close the session every time we load or save an object. This is important because the "lazy load" functionality in NHibernate requires a session to be open for as long as values haven't been loaded. For client-server apps this is a very bad thing: for one we don't want to maintain a session open (which implies an open connection to the database) while data is transfered from the server to the client and while the client loads the remainder of the data. And for two, depending on what type of data transfer protocol you are using, proxy objects might not be supported at all, resulting in incomplete data on the client. Therefore what we want is to transfer all the data from the server to the client at once. This is the reason why we don't support lazy-loading on this framework. However, it is altogether possible that you might be writing a 2-tier app where the client is sitting right on top of the database, and for this scenario I will show you how to modify the DatabaseObject to support lazy-loading on a future article.


Second, notice that on the first line of the Save and Load methods, there is a reference to the NHibernateHelper class. This class is the real deal for using NHibernate in conjunction with our previously written ObservableObject<T> class. The purpose of the NHibernateHelper class is simply to generate and keep track of object maps. It contains a public Configuration property so that any class that wants to create a session does so with the proper mappings.


internal sealed class NHibernateHelper
 {
        private const string CollectionTypeXmlAttribute = "collection-type";
        private const string ClassXmlAttribute = "class";
        private static readonly string[] RelationsXmlElements = { "many-to-many", "one-to-many" };

        private static readonly Dictionary<Type, Type> _MappedClasses;
        private static readonly Dictionary<string, Type> _CollectionElementsToTypes;
        private static readonly Configuration _Configuration;
        public static Configuration Configuration { get { return (_Configuration); } }

        static NHibernateHelper()
        {
            _MappedClasses = new Dictionary<Type, Type>();
            _CollectionElementsToTypes = new Dictionary<string, Type>();
            _CollectionElementsToTypes["bag"] = typeof(ObservableCollectionType<>); 
            _CollectionElementsToTypes["list"] = typeof(ObservableCollectionType<>);
            _CollectionElementsToTypes["set"] = typeof(ObservableSetType<>);
            _Configuration = new Configuration();
            _Configuration.Configure();

            // We first create overriden types for all classes that have a mapping. 
            // This is so that if there is a reference to another type (call it A) within a given type (call it B) 
            // we already have created the type A's overriden type and we can substitue B's map with the derived type.
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (Type type in assembly.GetTypes())
                {
                    if (type.GetCustomAttributes(typeof(ClassAttribute), false).Length > 0)
                    {
                        Type currentType = type;
                        Type overridenType = ObservableObject.CreateOverridenType(currentType);

                        _MappedClasses[currentType] = overridenType;
                    }
                }
            }

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (Type type in assembly.GetTypes())
                {
                    if (type.GetCustomAttributes(typeof(ClassAttribute), false).Length > 0) // This type defines a map
                    {
                        Type currentType = type;
                        Type overridenType = _MappedClasses[currentType];

                        // create a map XML string.
                        MemoryStream stream = new MemoryStream();
                        HbmSerializer.Default.Validate = true;
                        HbmSerializer.Default.Serialize(stream, currentType);
                        stream.Position = 0;

                        string currentTypeMap = new StreamReader(stream).ReadToEnd();
                        stream.Close();


                        // Collections are tricky business with NHibernate. By default NHibernate likes to deal with IList because internally
                        // it implements it's own custom persistant collections. What we need to do here is to add the "collection-type" attribute 
                        // of the X-to-many elements to point to our custom collection which implements INotifyCollectionChanged.
                        //XmlTextReader reader = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(currentTypeMap)));
                        while (reader.Read())
                        {
                            // we find an opening xml element of collection type (bag/set/list). We hope to find an X-to-many element within.
                            if (_CollectionElementsToTypes.Keys.Contains(reader.Name) && reader.NodeType == XmlNodeType.Element && reader.GetAttribute(CollectionTypeXmlAttribute) == null)
                            {
                                string elementName = reader.Name; // we store the current element name to later see if we find a matching close element.
                                int lineNumber = reader.LineNumber - 1;// LineNumber property is 1 based. we want to use 0 based arrays.

                                while (reader.Read())
                                {
                                    if (reader.Name == elementName && reader.NodeType == XmlNodeType.EndElement) // we found the closing element for the collection.
                                        break;

                                    // we found an opening relation element (X-to-many) with a "class" attribute defined 
                                    // note: the "class" attribute tells us what type the elements of the collection will be.
                                    string classNameAttribute = reader.GetAttribute(ClassXmlAttribute);
                                    if (RelationsXmlElements.Contains(reader.Name) && reader.NodeType == XmlNodeType.Element && classNameAttribute != null)
                                    {
                                        Type collectionItemType = Type.GetType(classNameAttribute);
                                        string attributeValue = _CollectionElementsToTypes[elementName].MakeGenericType(collectionItemType).ToString();
                                        attributeValue = attributeValue.Replace(collectionItemType.FullName, string.Format("{0}, {1}", collectionItemType.FullName, collectionItemType.Assembly.GetName().Name));
                                        attributeValue = attributeValue + ", " + Assembly.GetExecutingAssembly().GetName().Name;

                                        string[] lines = currentTypeMap.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.None);

                                        attributeValue = lines[lineNumber].Insert(lines[lineNumber].LastIndexOf(" "), string.Format(@" {0}=""{1}""", CollectionTypeXmlAttribute, attributeValue));

                                        currentTypeMap = currentTypeMap.Replace(lines[lineNumber], attributeValue);
                                    }
                                }
                            }
                        }

                        // because we want to offer the ObservableObject's functionality (I.E. property notifications and commands)
                        // we want to make sure that the mappings use the overriden type constructed by ObservableObject 
                        // instead of their base class counterparts.
                        foreach (KeyValuePair<Type, Type> mappedClass in _MappedClasses)
                        {
                            // NHibernate mappings sometimes allows specifying a type name without an assembly name. Therefore we
                            // want to make sure that we first replace the assembly qualified type name, and then the
                            // simple type name afterwards to avoid partial matches.
                            if (mappedClass.Key != currentType)
                            {
                                string assemblyQualifiedTypeName = string.Format(@"""{0}, {1}""", mappedClass.Key.FullName, mappedClass.Key.Assembly.GetName().Name);
                                if (currentTypeMap.Contains(assemblyQualifiedTypeName))
                                    currentTypeMap = currentTypeMap.Replace(assemblyQualifiedTypeName, string.Format(@"""{0}, {1}""", mappedClass.Value.FullName, mappedClass.Value.Assembly.GetName().Name));

                                string typeName = string.Format(@"""{0}""", mappedClass.Key.FullName);
                                if (currentTypeMap.Contains(typeName))
                                    currentTypeMap = currentTypeMap.Replace(typeName, string.Format(@"""{0}""", mappedClass.Value.FullName));
                            }
                        }

                        
                        // Create mappings for overriden type (they are exactly the same as the base type, but we just have to make sure to change the class name)
                        string className = string.Format(@"class name=""{0}, {1}""", currentType.FullName, currentType.Assembly.GetName().Name);
                        string overridenClassName = string.Format(@"class name=""{0}, {1}""", overridenType.FullName, overridenType.Assembly.GetName().Name);
                        string overridenTypeMap = currentTypeMap.Replace(className, overridenClassName);

                        // add type maps to NHibernate configuration
                        Configuration.AddInputStream(new MemoryStream(Encoding.UTF8.GetBytes(currentTypeMap)));
                        Configuration.AddInputStream(new MemoryStream(Encoding.UTF8.GetBytes(overridenTypeMap)));
                    }
                }
            }
        }
}

There are three important functons that the NHibernateHelper class must perform.
First, the NHibernateHelper class is in charge of generating mappings for the derived objects that are created by the ObservableObject class. Without these maps NHibernate would not be able to load any data onto our objects.
Second, it is in charge of replacing reference to custom types (types created by the end developer) with references to their derived types. In other words, we want to tell NHibernate to construct and load an object derived of the defined class so that we have the nice property changed and commands functionality provided by ObservableObject<T>.
Third, we also want to ensure that collections on the objects have notifications (so that they play nicely with WPF). Which brings me to the next section.



Collections


When designing types, it is quite likely that you are going to define collections just as frequently as single-object properties. Since WPF requires collections to implement INotifyCollectionChanged for binding purposes, we have to come up with a custom collection (or a set of custom collections in this case) that implements INotifyCollectionChanged and it is also able to persist itself using the NHibernate engine by inheriting PersistentGenericBag<T> or PersistentGenericSet<T>.


[Serializable]
public class DatabaseCollection<T> : PersistentGenericBag<T>, INotifyCollectionChanged 
{
 public event NotifyCollectionChangedEventHandler CollectionChanged;

 public DatabaseCollection(ISessionImplementor session) : base(session) { }

 public DatabaseCollection(ISessionImplementor session, ICollection<T> coll) : base(session, coll)
 {

  if (coll != null)
   ((INotifyCollectionChanged)coll).CollectionChanged += OnCollectionChanged;
        }

 public override void BeforeInitialize(ICollectionPersister persister, int anticipatedSize)
 {
  base.BeforeInitialize(persister, anticipatedSize);
  ((INotifyCollectionChanged)InternalBag).CollectionChanged += OnCollectionChanged;
 }

 protected void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
 {
  if (CollectionChanged != null)
   CollectionChanged(this, args);
 }
}

[Serializable]
public class DatabaseSet<T> : PersistentGenericSet<T>, INotifyCollectionChanged
{
 public event NotifyCollectionChangedEventHandler CollectionChanged;

 public DatabaseSet(ISessionImplementor session) : base(session) { }

 public DatabaseSet(ISessionImplementor session, ISet<T> coll) : base(session, coll)
 {
  if (coll != null)
   ((INotifyCollectionChanged)coll).CollectionChanged += OnCollectionChanged;
        }

 public override void BeforeInitialize(ICollectionPersister persister, int anticipatedSize)
 {
  base.BeforeInitialize(persister, anticipatedSize);
   ((INotifyCollectionChanged)gset).CollectionChanged += OnCollectionChanged;
 }

 protected void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
 {
  if (CollectionChanged != null) 
   CollectionChanged(this, args);
 }
}

When designing your types, you should use a DatabaseCollection<T> or DatabaseSet<T> as collection types, and in addition to getting collection notifications, thanks to the magic happening in NHibernateHelper you will automatically get items that implement INotifyPropertyChanged and have ICommands for all their methods.



DatabaseCollection Extensions


It wouldn't be object-oriented design if you weren't able to call a Load or a Save method straight from a collection and get the expected functionality from it. Thanks to the nice Extension Methods feature of the .Net framework 3.5 we can do just that not only for the DatabaseCollection<T> and DatabaseSet<T> but also for any collection type that implements ICollection<T>.


public static class DatabaseCollectionEx
    {
        public static void Save<T>(this ICollection<T> collection)
        {
            ISession session = NHibernateHelper.Configuration.BuildSessionFactory().OpenSession();
            foreach (var o in collection)
                session.SaveOrUpdate(o);
            session.Flush();
            session.Close();
        }

        public static void Load<T>(this ICollection<T> collection)
        {
            ISession session = NHibernateHelper.Configuration.BuildSessionFactory().OpenSession();
            foreach (T item in session.CreateCriteria(ObservableObject<T>.CreateOverridenType()).List())
                collection.Add(item);
            session.Flush();
            session.Close();
        }

        public static void Load<T>(this ICollection<T> collection, params ICriterion[] criteria)
        {
            ISession session = NHibernateHelper.Configuration.BuildSessionFactory().OpenSession();
            ICriteria c = session.CreateCriteria(ObservableObject<T>.CreateOverridenType());
            foreach (ICriterion criterion in criteria)
                c = c.Add(criterion);
            foreach (T item in c.List<T>())
                collection.Add(item);
            session.Flush();
            session.Close();
        }
    }

As you can see, besides saving content of a collection you can also load the contents of an entire table or a reduced subset by passing criteria to the Load method.


Here is a couple of sample business objects:


[Class(Name = "AndresLook.Address, AndresLook", Lazy = false, Table = "Address")]
    public abstract class Address : DatabaseObject<address>
{
        [Id(0, Name = "AddressId", Column = "AddressId")]
        [Generator(1, Class = "identity")]
        public virtual int AddressId { get; set; }
        [Property(Column = "ContactId")]
        public virtual int ContactId { get; set; }
        [Property(Column = "Address1")]
        public virtual string Address1 { get; set; }
    }

[Class(Name="AndresLook.Contact, AndresLook", Lazy=false, Table="Contact")]
    public abstract class Contact : DatabaseObject<contact>
    {
        [Id(0, Name="ContactId", Column="ContactId")]
        [Generator(1, Class = "identity")]
        public virtual int ContactId { get; set; }

        [Property(Column="FirstName")]
        public virtual string FirstName { get; set; }

        [Property(Column="LastName")]
        public virtual string LastName { get; set; }

        [Bag(0, Name = "Addresses", Table = "Address", Lazy = CollectionLazy.False, Cascade = "save-update")]
        [Key(1, Column = "ContactId")]
        [Index(2, Column="AddressId")]
        [OneToMany(3, Class = "AndresLook.Address, AndresLook")]
        public virtual IList<address>
Addresses { get; set; }

        public Contact()
        {
            // We define "Addresses" as an observablecollection by default
            // if we instantiate Contact using the .New() method we should be able
            // to add entries to Addresses and using the .Save() method should
            // save those entries to the database as expected.
            Addresses = new ObservableCollection<address>();
        }
    }

And here is how you can tap onto the databse functionality:


Contact c = Contact.New();
c.Load(1);

List<address>
a = new List<address>();
a.Load(NHibernate.Criterion.Expression.Eq("AddressId", 1));

In my next article, I'll demonstrate how to create a CommunicationObject that transfer data from a server to a client and vice versa.






Tuesday, January 5, 2010

MultiuseModel-View (MMV) Object modeling pattern with WPF and WCF: The Foundation



Download sample ObservableObject project



In my previous article I went over how to break up a multiuse object into logical parts. In this article I will talk about an ObservableObject: an object that notifies WPF of changes.



The ObservableObject Class


There are two type of members that you can bind in a WPF app: properties and methods. Requirements for binding properties is fairly straight forward: one must implement INotifyPropertyChanged. To bind a method, on the other hand, we must actually have a property of type ICommand for each method we want to bind to.


Implementing INotifyPropertyChanged simply consists of raising the PropertyChanged event every time a property changes. The problem lies in making a child class of ObservableObject to raise the event without having the developer of the child class call it himself/herself. The best solution for this problem is to use Reflection.Emit to construct a child class of the templated class and override the properties' set method to raise the event after executing the template's set method logic.


foreach (PropertyInfo property in parentType.GetProperties())
                {
                    method = parentType.GetMethod("set_" + property.Name);
                    methodBuilder = typeBuilder.DefineMethod(method.Name, method.Attributes, method.ReturnType, method.GetParameters().Select(pi => pi.ParameterType).ToArray());
                    il = methodBuilder.GetILGenerator();
                    locAi = il.DeclareLocal(typeof(ArgIterator));

                    il.Emit(OpCodes.Nop);
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldarg_1);
                    il.EmitCall(OpCodes.Call, method, null);
                    il.Emit(OpCodes.Nop);
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldstr, property.Name);
                    il.EmitCall(OpCodes.Call, parentType.GetMethod("OnPropertyChange", BindingFlags.NonPublic | BindingFlags.Instance), null);
                    il.Emit(OpCodes.Nop);
                    il.Emit(OpCodes.Ret);
                    typeBuilder.DefineMethodOverride(methodBuilder, method);
                }

With this in mind, adding ICommands for methods becomes just as easy: we can use the same TypeBuilder to add new properties of type ICommand for each public method.



foreach (MethodInfo mi in parentType.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(methodInfo => !methodInfo.Name.StartsWith("get_") && !methodInfo.Name.StartsWith("set_") && !methodInfo.Name.StartsWith("add_") && !methodInfo.Name.StartsWith("remove_")))
                {
                    FieldBuilder commandField = typeBuilder.DefineField("_" + mi.Name + cExtendedTypesCommandPostfix, typeof(DelegateCommand), FieldAttributes.Private);

                    MethodBuilder commandGetMethod = typeBuilder.DefineMethod("get_" + mi.Name + cExtendedTypesCommandPostfix, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, typeof(ICommand), Type.EmptyTypes);
                    ILGenerator commandGetMethodIL = commandGetMethod.GetILGenerator();

                    var commandNullLabel = commandGetMethodIL.DefineLabel();
                    var defaultLabel = commandGetMethodIL.DefineLabel();

                    commandGetMethodIL.Emit(OpCodes.Nop);
                    commandGetMethodIL.Emit(OpCodes.Ldarg_0);
                    commandGetMethodIL.Emit(OpCodes.Ldfld, commandField);
                    commandGetMethodIL.Emit(OpCodes.Ldnull);
                    commandGetMethodIL.Emit(OpCodes.Ceq);
                    commandGetMethodIL.Emit(OpCodes.Brfalse, commandNullLabel);
                    commandGetMethodIL.Emit(OpCodes.Ldarg_0);
                    commandGetMethodIL.Emit(OpCodes.Ldarg_0);
                    commandGetMethodIL.Emit(OpCodes.Ldftn, mi);
                    commandGetMethodIL.Emit(OpCodes.Newobj, typeof(Action).GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));
                    commandGetMethodIL.Emit(OpCodes.Newobj, typeof(DelegateCommand).GetConstructor(new Type[] { typeof(Action) }));
                    commandGetMethodIL.Emit(OpCodes.Stfld, commandField);
                    commandGetMethodIL.MarkLabel(commandNullLabel);
                    commandGetMethodIL.Emit(OpCodes.Ldarg_0);
                    commandGetMethodIL.Emit(OpCodes.Ldfld, commandField);
                    commandGetMethodIL.Emit(OpCodes.Ret);

                    PropertyBuilder commandProperty = typeBuilder.DefineProperty(mi.Name + cExtendedTypesCommandPostfix, PropertyAttributes.HasDefault, typeof(ICommand), null);
                    commandProperty.SetGetMethod(commandGetMethod);
                }

Now for all of this to work we need to make sure two things happen: first the consumer of the template object should actually get an instance of the derived type. And second, since the consumer is actually using a child class of the type he/she declared, we must ensure that reflection and typing compatibility is achieved. To do this, we must first of all provide a means of instantiating a new object (with a New() static method) and we must also override the GetType() of the child type we have created to return an instance of the template's Type class.


MethodInfo method = typeof(object).GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { }, null);
                MethodBuilder methodBuilder = typeBuilder.DefineMethod(method.Name, method.Attributes, typeof(Type), method.GetParameters().Select(pi => pi.ParameterType).ToArray());
                ILGenerator il = methodBuilder.GetILGenerator();
                LocalBuilder locAi = il.DeclareLocal(typeof(ArgIterator));

                il.Emit(OpCodes.Ldtoken, parentType);
                il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static), null);
                il.Emit(OpCodes.Stloc_0);
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ret);

public static T New()
        {
            return ((T)Activator.CreateInstance(CreateOverridenType(typeof(T))));
        }

In my next article, I'll demonstrate how to create an enterprise level DatabaseObject and DatabaseCollection classes.




Monday, January 4, 2010

MultiuseModel-View (MMV) Object modeling pattern with WPF and WCF: Genesis



In my previous article I gave a basic introduction to the Multiuse-Model View pattern. In this short article I will explain in detail the concepts behind a MMV library.



The Multiuse-Object Theory


A well organized framework is highly dependent on inheritance and encapsulation to avoid messy code and unnecessary overhead. Let's take the WPF framework itself for instance: when you are dealing with controls... say... a Button, you are dealing with a class that inherits from DispatcherObject, DependencyObject, Visual, UIElement, FrameworkElement, Control, ContentControl and ButtonBase. Each of these parent classes provide a different piece of functionality to their children such that by the time we get to deal with the Button class, we only have to worry about a few methods and properties to make the button show up on the screen and display text (or other stuff) inside and handle user events.
Likewise, with our Multiuse-Model approach, we want a set of classes that provide basic functionality to our business objects in order to encapsulate operations related to databases, client-server communications and even property notification changes.
In my previous article I wrote about lumping all this functionality in one single class, the MultiuseObject class, however, for large scale applications this would be cumbersome since the amount of functionality in a realistic framework is excessive for a single class. For this reason it is better to slice and dice each set of functionality into their own classes. At a minimum you should have the following classes as parents of your business objects:


  • ObservableObject: provides implementation of INotifyPropertyChanged for properties and ICommands for methods.
  • DatabaseObject: provides functionality to retrieve and store information on a database (there are many good data-layer libraries already, this object would wrap their functionality).
  • CommunicationObject: provides client-server communications.
  • MultiuseObject: wraps all functionality in a nice and neat package.

These classes are listed in order of inheritance, since, it is likely that sometimes you might not need to deal with the entire functionality. For example, sometimes you will have UI-only objects that would inherit straight from ObservableObject opposed to MultiuseObject.

In my next article, I'll demonstrate how to create an enterprise level ObservableObject class.