Tuesday, August 6, 2013


MEF Part 3


MEF has an awesome facility that gives you a lot of power over your exportinG and importing that I am going to describe to you in this post.

I first started using MEF I faced a problem early on with importing many objects of a shared class or interface. In some cases I wanted to control which objects I loaded based on some attribute. My first implementation was very naive. I created read only properties on my interfaces (only getters, no setters). This allowed my objects to expose to the importing container various information or metadata about themselves. I then created factory methods which used some LINQ sugar do return objects based on metadata filtering.


This approach, while it worked, was flawed for many reasons. The least of which is that I would have to load each object and examine it's property before I can determine it was the object I needed or wanted in that situation. If the objects are small and lightweight this isn't too much of an issue. While it might be a candidate for optimization later it probably is fine in those situations. Imagine, however, your objects open database connections, file streams, sockets, etc... In those cases it would be prohibitively expensive to create all those objects just to look at a static string exposed by the object.Along comes the Lazy class. This class provides an extension to Lazy for object metadata. You can use it to "peek" at the metadata of the exported types without actually loading the type. Let's look at some code.



public interface IMessageSender
{
    void Send(string message);
}

[Export(typeof(IMessageSender))]
[ExportMetadata("transport", "smtp")]
public class EmailSender : IMessageSender
{
    public void Send(string message)
    {
    }
}

So, in this example I created an interface called IMessageSender. I created an implementation class called EmailSender. I'm exporting the type IMessageSender (again, by contract is more flexible than by type). I'm also adding some metadata to the export. In this case I'm adding a key called "transport" with a value of "smtp". Since the default implementation of the attribute class exposes a Dictionary we have to declare our import like so:


[ImportMany]
IEnumerable<IMessageSender> _senders;

Now we can use a little LINQ sugar to find our objects:

   var smtpSender = 
       _senders
       .Where((lazy) => lazy.Metadata.ContainsKey("transport") 
                    && ((string)lazy.Metadata["transport"] == "smtp"))
       .Select(lazy => lazy.Value).FirstOrDefault();


And there you have it! Now that is some sweet goodness. Next part I'll show how you can extend ExportAttribute to provide your own contract for Metadata and not have to search for a key in a dictionary and convert the key to a particular type and hope the conversion succeeds without losing data.

MEF Part 2 

On the last installment I demonstrated how to export, import, and compose types. This still doesn't solve the problem of decoupling the components. The composing code still needs a reference to a particular type which defeats the purpose of decoupling and late binding.

The key to solving that problem is to use interfaces. Interfaces separate implementation details from an objects contract, which is exactly what we need. We want the objects to behave same but we don't care about the details of how they were created or where they live. We can create an interface in a common library and reference that interface when we compose the objects. When creating extensions the common library will also be referenced and that gives us the glue we need to abstract the implementation details.

Let's look at an example interface.  This is a simple example, but you can obviously create something more complex for your needs.
public interface IPlugin
{
   string GetData();
}

And here is an example of an exporter:
[Export(typeof(IPlugin))]
 public class MyPlugin : IPlugin
 {
  public string GetData()
  {
   return "Hello World from MyPlugin";
  }
 }
Here is some sample code demonstrating how we can use the above features:
public class Program
{
   [ImportMany]
   protected IEnumerable<IPlugin> _plugins;
   static void Main(string [] args)
   {
       Program p = new Program();
       p.Run(args);
   }
 
   public void Run(string [] args)
   {
       string pluginDirectory = Path.GetFullPath(@"..\..\Plugins");
 
      // a catalog to aggregate other catalogs
      var aggregateCatalog = new AggregateCatalog();
 
      // a directory catalog, to load parts from dlls in the Plugins folder
      var directoryCatalog = new DirectoryCatalog(pluginDirectory, "*.dll");
 
      // an assembly catalog to load information about parts from this assembly
      var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
 
      aggregateCatalog.Catalogs.Add(directoryCatalog);
      aggregateCatalog.Catalogs.Add(assemblyCatalog);
 
      // create a container for our catalogs
      var container = new CompositionContainer(aggregateCatalog);
 
      // finally, compose the parts
      container.ComposeParts(this);
      foreach(IPlugin plugin in _plugins)
      {
         Console.WriteLine(plugin.GetData());
      }
   }   
}

And again, there you have it. Now the client (or composing container) only needs to reference the interface which is in a shared library. Many plugin dlls can be scanned and many plugin types can be included in a single dll. All of them will be included in the list imported by the client.
From May 2009:

Oh man, oh man. The .Net team has outdone themselves this time. Not only have they given us the sugar of null coalescing operators, covariance/contravariance, and optional parameters, they have handed us an outstanding framework we can use to decouple large systems.

 Microsoft had something good going with late binding but the implementation of COM/DCOM was flawed. A global registry which allowed only one object of a type to be registered at a time was not very flexible. They finally got it right with MEF. You can now create flexible, maintainable, testable, and extensible components for your systems.

I'm going to show how you can do that using MEF and a few lines of code. First and foremost, MEF, in it's simplest form, is Dependency Injection (or DI). It's important to understand the concept of Inversion of Control (IOC) and DI before you can understand the benefits of MEF. You can probably still use it, but it's full power will not be realized until those key concepts are understood.

With that in mind I'm going to assume the reader knows something about those concepts and will be using terms without explaining them. To understand the mechanics of MEF is easy. It centers around three key concepts. There are exporters, importers, and containers. The exporters will export a type, usually in some executable form. The importers will import certain types. The container allows composition of exporters to importers. The container is the "glue" that brings the importers and exporters together.

Let's look at some sample code that imports a certain type:
[Import]
private SomeType _objectToImport;

 This example illustrates field injection. The Import attribute tells the container that this class is expecting a certain type. If the type is not specified in the attribute then it's assumed to be the type of the field that it decorates.

 Here is another example that shows how to import many of a particular type:

[ImportMany]
private IEnumerable _objectToImportList;

Again, this illustrates field injection but the difference is instead of expecting a single object I will be expecting a list of objects (0 or more) which is specified by the ImportMany attribute.

 Now let's look at some code that exports an object:
// you can either specify a type, or allow MEF to reflect on the type
[Export(typeof(SomeType))] 
public class SomeType
{
   public string Name
   {
      get;
      set;
   }
}
Now, let's look at the glue code:
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

...

[ImportMany]
private IEnumerable _objectToImportList;

// a catalog to aggregate other catalogs
var aggregateCatalog = new AggregateCatalog();

// a directory catalog, to load parts from dlls in the Plugins folder
var directoryCatalog = new DirectoryCatalog(pluginDirectory, "*.dll");

// an assembly catalog to load information about parts from this assembly
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
aggregateCatalog.Catalogs.Add(directoryCatalog);
aggregateCatalog.Catalogs.Add(assemblyCatalog);

// create a container for our catalogs
var container = new CompositionContainer(aggregateCatalog);


// finally, compose the parts
container.ComposeParts(this);

// at this point this._objectToImportList should be filled with SomeType objects
// which are loaded from the various catalogs



And there you have it. Simple and sweet.

In my next installment I'll show how to use an interface in a common library to provide ultimate decoupling.