Thursday, November 12, 2009

An Introduction to MEF

Have you ever attempted to write an extensible application?  You know the kind. The applications where your boss wants to be able to add stuff to it without rewriting the entire application and with minimum costs.  Or the type of application you want to release out to the community and provide a way for them to add their own customizations to it.  We have all seen these types of applications; however, if you have ever attempted to write such, it is usually a pain to developer the core application or a pain to develop the extensions or plug-ins.  Thankfully the Managed Extensibility Framework (MEF) is available to those of us that have extensibility needs inside of the application.

Origins and Model

MEF was developed from an initiative within Microsoft in order to simply the creation of building extensible applications.  Developed by Glenn Block and others, the team developed a framework that handled the discovery and composition of the plug-ins/parts to make application extensibility easy to pickup and utilize.  In MEF, a model was developed where decorated parts, containing the extensions of the application, are discovered through catalogs and then composed within a composition container.  What is nice about this model is that it allows for composition at many levels so parts or extensions can include the ability to be extended in addition to extending an application itself (i.e. plug-ins for plug-ins).

How Does MEF Differ From IoC Containers?

During an interview on Hanselminutes episode 148 (Jan 28th, 2009), Scott Hanselman asks Glenn Block how MEF differs from IoC containers.  Glenn provided a very clear (to me) definition of the difference by saying...

You use MEF to manage a set of unknown things. You use IoC containers to manage a set of known things.

Looking at the quote, Glenn makes a good point in that when developers use an IoC container, they typically know of the various types and dependencies they are wiring up through an IoC container.  Sometimes this is configuration based to address differences between environments or just dependencies inside of the code in general. However, when you look at building an application that will allow 3rd party extensions, there's no way of knowing what will be added on.  Now MEF can act like an IoC container but to truly think of it in only that light really places mental limitations on what it can accomplish.

Writing the Hello World

When I started learning MEF, changes had been done since a number of the examples available online were created.  Since we're just getting familiar with MEF in this post, below is a very simple example where MEF is used similarly to an IoC container within a console application.  We'll take this example and greatly expand on it in the next couple of posts; however, for now, I want to just demonstrate the absolute basics to MEF. Before we dive into the code, we need to download the MEF assembly so that we can reference it in our application.

To get the necessary components for integrating MEF into our application, we need to head out to the MEF Project out at Codeplex and click on the Downloads section.  In this series, we'll be focused on MEF Preview (Beta 2) which is compatible with .Net v3.5. In the Downloads section, there should be a link for MEF_Beta_2.zip.  Download and unzip this file.  In the bin directory, you'll want to copy the System.ComponentModel.Composition.dll file.  This is the assembly used to harness the power of MEF.

Now that we have the assembly downloaded, we can create a new console application and reference it. In this demonstration, our simple console application will just output a message.  Very simple, very impractical really but we'll add more practicality over the next posts.  Our console application will need 2 classes; Program.cs and SimpleMessage.cs (shown below)

Program.cs

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample1
   7:  {
   8:      class Program
   9:      {
  10:          [Import()]
  11:          string Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

SimpleMessage.cs

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample1
   4:  {
   5:      class SimpleMessage        
   6:      {
   7:          [Export()]
   8:          string MyMessage
   9:          {
  10:              get { return "Hello, Extensible World"; }
  11:          }
  12:      }
  13:  }
There's 3 things here we need to look at.  The Program class contains a string property called Message which is decorated with the [Import()] attribute.  This attribute tells MEF that it is an entry point for extensibility.  The 2nd thing to take note of is that our SimpleMessage class contains a string property called MyMessage and returns the message we want to output to the console window.  This property is decorated with the [Export()] attribute which informs MEF that it can be mapped to an [Import()] member of another type.  Lastly, there are the following 3 lines in our Program class's Compose() method...
   1:  var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
   2:  var container = new CompositionContainer(catalog);
   3:  container.ComposeParts(this);

These 3 lines are used by MEF to discover what parts are available in the current assembly to be imported and compose the parts into the appropriate instance that is extensible (in this case our instance of the Program class).  When we run the project, we see that our message is displayed in the console window without manually mapping SimpleMessage.MyMessage to Program.Message.


This is just a very quick and simple taste of what MEF can do.  In the following posts, we'll dive deeper into declaring Imports and Exports to ensure there not any conflicts during the mapping process as well as demonstrate some options we have on looking for parts outside of our current assembly by using different catalogs.  Until then, please feel free to check out the source code and links located at the bottom of this article for more information on MEF.

Other Resources


kick it on DotNetKicks.comShout it

6 comments:

  1. You’ve made my day a happy one. The topic is clearly explained with less Grammar, straight to the point.

    I understand what MEF is all about now. After reading many articles on the Topic yours is simply the best.

    Thanks for your effort

    Terry Amusa (Developer)

    ReplyDelete
  2. @Terry

    Thanks. This post was really just to show the simplest example. Definitely stay tuned for the next posts in the series which will help explain how to do more explicit mapping techniques.

    ReplyDelete
  3. Very nice explanation. It's a shame there aren't more MEF examples like this online.

    ReplyDelete
  4. Absolutely awesome !!! thanks a lot. I will read your all posts on MEF...

    Regards,
    //R

    ReplyDelete
  5. Great article, very simple and to-the-point. I'll definitely be reading your other MEF articles since I'm trying learn more about MEF and how I can use it in some of my existing and upcoming projects.

    Many thanks

    ReplyDelete
  6. Excellent, speciallly for beginners.....

    ReplyDelete