Plug-ins / Modules Development with MEF -Part II

Goldytech
Posted by in Others category on for Beginner level | Views : 14264 red flag
Rating: 5 out of 5  
 1 vote(s)

This is part 2 of the series of how to create a decoupled application using Managed Extensibility Framework (MEF)
INTRODUCTION
This is the continuation of my earlier post. I strongly encourage the readers to stop here and read the part one of this series if they haven't read it yet. In part one we looked at the brief introduction on MEF and a practical scenario where this framework can be implemented. We talked about HRMS , I have code named it as MangoPeople :). This is not an HR solution but just peeps into it how MEF can help you to build these type of enterprise apps. So let us get jump started into it.
MEF APPLICATION

Our MangoPeople HR solution is built on WPF using Visual Studio 2010 RC in .Net Framework 4.The Visual Studio solution consists of 5 projects as shown in figure below.

solutionexplorer

  1. MangoPeopleHR : This is based on WPF Application Template. It is an empty shell and just have one Xaml Window. Look at the screen shot below which will give you the fair idea.
    MangoPeople Main Window

    On the Left hand side you will see the Modules that are available. If your client who has not purchased any of the modules , those links will not be active (You wont get an hand mouse pointer on that module link). On the Right hand side there is a content control which will hosts the main window or entry point screens of the modules selected. The output of this project is an .exe
  2. CommonStuff: This is project based on the standard windows class library project. It contains the helper class of handling commands for ViewModel and the other class has the MEF contract interface.
  3. PersonalModule:
  4. PayrollModule:
  5. RecruitmentModule:

The items 3,4 and 5 are based on WPF User Control Library Project Template whose output is the dll. I hope you must have now got the overall idea of the solution. Now the catch here is that all these modules should be pluggable. If you add them they become active and vice-versa. So to make them active you must copy the module dll into one of the designated folder, I call it MangoPeopleLic. In this folder if the module dll is present that module link will be active if removed it will be inactive. So time has come now to see the inside stuff.
MEF IMPLEMENTATION
Though these modules are independent of the main application. There should be some glue which should bind them once they are plugged in (dll is copied in the designated folder) and that is where the MEF contracts or interface comes in and play a vital role in overall MEF implementation. Let us look at the code
namespace CommonStuff 
{
    public interface  IContract
    {
        string ModuleName { get; }
    }
}
The Icontract interface has only one read only property called ModuleName. Now any type that needs to expose these functionalities should be decorated with the Export attribute with typeof parameter. In our scenario all our UserControl main class or the entry points of every module should have this attribute. See the code below of one of PersonalMainView.xaml.cs
using System.Windows.Controls; 
using CommonStuff;
using System.ComponentModel.Composition;
namespace PersonalModule
{
    /// <summary>
    /// Interaction logic for MainPersonalView.xaml
    /// </summary>
    ///
    [Export(typeof (IContract))]
    [ExportMetadata("ModuleName","Personal")]
    [ExportMetadata("ModuleId",1)]
    public partial class MainPersonalView : UserControl,IContract
    {
        public MainPersonalView()
        {
            InitializeComponent();
        }
        #region IContract Members
        public string ModuleName
        {
            get { return "Personal"; }
        }         
    }
}
The above code besides inheriting the UserControl class also implement the IContract interface. It is also decorated with the Export and ExportMetaData attributes.All MangoPeopleHR modules user control classes have the same code except for the ExportMetaData attributes values and IContract interface property value. So we are done from the modules perspective and now let us jump to the MainWindowViewModel class which gets binded to the MainWindow. One of the most important property in this class is ModulesPurchased.
[ImportMany] 
public Lazy<IContract,IDictionary<string ,object>>[] ModulesPurchased  { get; set; }
This property is decorated with ImportMany attribute to load all the required composable parts also it is of Lazy type , which means the parts will be loaded on demand. Remember I talked about the glue earlier which binds the main exe with all the dll. This property is the glue here. In modules project the usercontrol classes if you remember we were using Export attribute of same contract and here we are using ImportMany attribute of the same contract. Does that make sense to you , Great !. Now let us look at the other methods which put MEF on fire.

private CompositionContainer GetLicenseInfo()
{
            var objCatalog = new AggregateCatalog();
            var objAssembly = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
            objCatalog.Catalogs.Add(objAssembly);
            objCatalog.Catalogs.Add (new DirectoryCatalog(LicenceDirectory ));
            var container=new CompositionContainer(objCatalog );
            return container ;
}

The above code listing does the job of adding all the parts in the repository. We use AssemblyCatalog and DictionaryCatalog. The LicenceDirectory is the class variable which stores the path of the folder where all modules dll will be there. So now we have parts in the repository so now let us compose them , the code of which is described below.

public  bool CheckLicences()
       {
           _LicenceComposionContainer = GetLicenseInfo();
           try
           {
               _LicenceComposionContainer.ComposeParts(this);
           }
           catch (Exception)
           {
               System.Windows.MessageBox.Show("Unable to Retrieve the License Information");
               return false;
           }
           return true;
       }

After getting the value of the CompositionContainer from the GetLicenseInfo method. It tries to call the ComposeParts method.Returns a boolean value dependent on this method call. And now finally let us see the Command method which enables or disables the hyperlink based on the dlls available in the License directory.

private bool  CanModuleSelectExecute(object param)
{
            bool isAllowed=false;
            foreach (var item in this.ModulesPurchased )
            {
                if (param.ToString().Equals(item.Metadata["ModuleId"].ToString()))
                {
                    isAllowed = true;
                    break;
                }
                else
                {
                    isAllowed =false ;
                }
            }
            return isAllowed;
}

Here we rotate in the loop and compare the param value with the metadata in the array of ModulesPurchased property. If the match is found the function returns true which will enable the link else the link will be disabled. The param parameter of object type is binded in the Xaml via CommandParameter property.
CLOSURE
So you just saw how MEF simplifies the application partitioning.Though in past we had such frameworks which provided this type of functionalities like Composite Application Blocks,PRISM and Unity to name few. But MEF is different and with ease it can be integrated. It is now the official part of the CLR, what more do you accept to understand its importance.So get started now and start using MEF. You can download the sample code of this post from here. Please ensure to change the value of LicenseDirectory variable to suit to your enviornment otherwise you will get error. Do let me know your thoughts on MEF.
Page copy protected against web site content infringement by Copyscape

About the Author

Goldytech
Full Name: Muhammad Afzal Qureshi
Member Level: Bronze
Member Status: Member
Member Since: 8/4/2009 10:58:17 PM
Country: India

http://goldytech.wordpress.com
Hello Everyone Myself Muhammad Afzal , aka GoldyTech. Thats my pen name. I reside in India and work as a solution Architect on .NET platform. I hope you must have enjoyed reading my blog. Please leave your comments or suggestions good or bad and help me to improve

Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)