One MEF’ed Up App

May 24, 2010 at 8:13 AMmgordon

I’ve been working on a personal project and wanted to allow a plug-in architecture.  I have, in the past, written the code to dynamically discover assemblies in a particular location, load them and reflect on the types they contained to see if any implemented a certain interface I was looking for.  I have been hearing about MEF and decided to see if it offered anything by way of lessoning the pain of implementing plug-ins.

 

First, let me make it clear that the examples that follow work with the version of MEF installed with the Visual Studio 2010 release.  MEF is drop-dead easy to work with, but I did find it a bit frustrating to have to sift through examples I found on the web that no longer worked.  My recommendation is to look at the various tutorials available online to get an idea of what MEF is and what it’s designed to do.  However, trust only the MEF site on CodePlex for determining the exact syntax to use.

 

What I want from my application is to be able to drop assemblies that contain plug-in’s into a sub folder beneath my bin folder and have them be discovered and loaded into my application with minimal fuss and muss.  I created a class to manage all of this for me.  After setting a reference to System.ComponentModel.Composition, I created a collection property to contain all my plug-ins.

 

Import Collection
  1. [ImportMany]
  2. public IEnumerable<IExtension> Extensions { get; set; }

 

Each plug-in needs to implement the interface, IExtension.  I have added the [ImportMany] attribute to this property to tell MEF to add all classes that implement this interface to my collection.  Next, I created a class that implements the IExtension interface that I expect to be imported as a plug-in.

 

Plug-in class
  1. [Export(typeof(IExtension))]
  2.     public class STMWeather : ExtensionBase, IExtension

 

Here, I have created a class that implements IExtension and decorated it wth the [Export] attribute.  Since the class is not of type IExtension, I have to let MEF know to cast it as such before exporting, thus the parameter in the attribute.

 

At this point, I have a class to export and a property expecting to import, but how do I trigger the magic that pulls these two together?  Back in the ExtentionManager class (containing the property I’m importing into), I add the following code to the constructor.

 

Actual Composition
  1. public ExtensionManager()
  2. {
  3.     DirectoryCatalog catalog = null;
  4.     CompositionContainer container = null;
  5.     try
  6.     {
  7.         catalog = new DirectoryCatalog(@".\Extensions");
  8.         container = new CompositionContainer(catalog);
  9.         container.ComposeParts(this);
  10.     }
  11.     finally
  12.     {
  13.         catalog.Dispose();
  14.         container.Dispose();
  15.     }
  16. }

 

I create a catalog to contain all my plug-in’s and a container.  I think of the container as the witch’s caldron where the magic happens.  Next, I create the catalog by pointing it to the directory where my plug-ins live.  MEF will scan the folder and identify types matching what I’m expecting to import which are also decorated with the Export attribute.  Each of these will be added to the catalog.  Then, the container is created and it is passed the catalog.  Now, I make a call to ComposeParts and pass it an instance of the ExtensionManager.  This call tells MEF to use the catalog and try to satisfy any imports on the passed in instance with exports in the catalog.  When this call completes, my property will contain an instance of each plug-in found in my .\Extensions directory.

Having written the code to do all this manually, I can certainly appreciate the work that’s being done for me, here.  Very simple and very powerful.

Posted in: MEF

Tags: