CslaContrib.MEF and Repository pattern with Csla4

Introduction

MEF has become a standard component in .NET4 and so become an easy starting point for developers for IoC and much more.

In this article I will focus how you can easily use MEF to create an injectable Repository data access into  your Csla business objects. This will help you to create more testable code as your unit tests can inject their own implementation of data access or even just fake som data access. The accompanying sample code uses DataPortal_XYZ methods and can be downloaded from http://cslacontrib.codeplex.com

Csla implements several design patterns including Mobile Objects and Factory methods. So your business objects should not know if the data access happens inline (one-tier) or  on a server (two-tier). This is handled by configuration of the DataPortal and the sample code shown here will work in both configurations.

The Repository pattern is widely described in other articles but here is short introduction for typical usage in Csla:

  1. You have a known set of repository data access objects.
  2. You have defined Interfaces for your data access code.
  3. You want to inject the data access code into your BO.

Ioc static class

The Ioc static class holds the MEF container and will initialized when first call is made. This class also provides a method for test code to supply an externally configured container for data access or fake data.

Custom base classes

The first step is to create custom base classes. This will be the base classes that your BOs inherit from and will make sure to provide the Imports in your objects.

These classes must handle the OnDataPortalInvoke, OnDeserialized and Child_OnDataPortalInvoke (when applicable) events to inject dependencies.

The OnDataPortalInvoke is called by the DataPortal before it call the DataPortal_XYZ methods in both one-tier and two-tier configuration.
The Child_OnDataPortalInvoke is called by the ChildDataPortal beore it call the Child_XYZ methods.
the OnDeserialized is called when the object is deserialized on server or client.

Sample code for MefBusinessBase:

  public class MefBusinessBase<T> : BusinessBase<T> where T : BusinessBase<T>  
  {    
    protected override void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)    
    {      
       Inject();       //inject dependencies into instance      
       base.DataPortal_OnDataPortalInvoke(e);    //call base class   
    }     

    protected override void Child_OnDataPortalInvoke(DataPortalEventArgs e)    
    {          
       Inject();      //inject dependencies into instance      

       base.Child_OnDataPortalInvoke(e);   //call base class    
    }   

    protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)    
    {      
       Inject();      
       base.OnDeserialized(context);    
    } 

    private void Inject()    
    {      
       Ioc.Container.ComposeParts(this);    
    }  
  }

The following classes are supplied in CslaContrib.MEF:

MefBusinessBase
MefBusinessBindingListBase
MefBusinessListBase
MefCommandBase
MefDynamicBindingListBase
MefDynamicListBase
MefNameValueList
MefReadOnlyBase
MefReadOnlyBindingList
MefReadOnlyListBase

Define repository object and data access

In order to use IoC you will create interfaces for the data access code and known repository objects. The smallest samples I could think of is shown here:

  public interface IRootDataAccess  
  {    
     RootData Get(int id);  
  }   

  public class RootData  
  {    
    public int Id { get; set; }    
    public string Name { get; set; }  
  } 

Use MEF to satisfy Imports in your data access

Define injectable properties in your business objects like this:

    [NonSerialized, NotUndoable]    
    private IRootDataAccess _myRootDataAccess;

    [Import(typeof(IRootDataAccess))]    
    public IRootDataAccess MyRootDataAccess    
    {
       get { return _myRootDataAccess; }
       set { _myRootDataAccess = value; }
     }
 Note – You must use a private backing field and mark the field as both NonSerialized and NotUndoable as injected properties should NOT be included in a two-tier application nor be part of the N-Level undo. 

So the data access would look like this:

    public static MyRoot GetRoot(int id)
    {
       return DataPortal.Fetch<MyRoot>(id);
    }    

    public void DataPortal_Fetch(int criteria)
    {
      var data = MyRootDataAccess.Get(criteria);
      using (BypassPropertyChecks) 
      { 
        Id = data.Id; 
        Name = data.Name; 
      }    
   }
In the fetch method the BusinessObject has been supplied with a repository object and knows that this object has a Get method that accepts an int parameter. 

DataAccess classes

 

 

Create classes that Export and implement the data access interfaces:

  [Export(typeof(IRootDataAccess))]
  public class MyRootDataAccess : IRootDataAccess
  {
    public RootData Get(int id)
    {
      return new RootData() { Id = id, Name = "Ole Olsen" };
    }
  }


The Ioc static class will load Exports from all assemblies in the current folder and the executing assembly (for a client application). So when your business objects inherits from the MefXYZ base classes  you will automatically get the available Exports which in your production environment should only be the production assemblies (no test assemblies). 

The good thing here is that when you create unit tests – you can supply your own configured container to the IoC class that will typically do fake data access while the production code will do actual data acces to a database or webservice.

  

I hope this will encourage and help you to use MEF if you want to use the repository pattern in a Csla project. All sample code can be found in the Samples folder in CslaContrib and the CslaContrib.MEF project is in the CslaContrib trunk.

 

Advertisements

4 thoughts on “CslaContrib.MEF and Repository pattern with Csla4

  1. Matt Ruma

    Hi Jonny! Thanks for this information … and your help on the CSLA forums … this is getting me much closer where I want to be!

    Reply
  2. Dane Vinson

    Can you point me to the source code referenced in this post? I do not see it at the Cslacontrib Codeplex site referenced above. The download on that page is from prior to the date of this post and has no MEF related code.

    Thanks

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s