Addicted To MEF – Part 1

Writing

As with any new tool that hits the scene, I always feel the need to explore and evaluate it. Right now there are many many new tools coming out of Microsoft and so I have to cherry pick the ones I am most interested in. Well, I saw just a few days ago that Microsoft had just released Preview 3 of its Managed Extensibility Framework, also known as MEF. I’ve been reading about it for a while, and I know that two people that I admire, Glenn Block and Hamilton Verissimo (of Castle fame) are both working as PMs on the team. I have also recently been working on a lot of architecture design stuff for my employer (Dominion Digital) and so I was very interested to explore MEF further and see what it could offer me.

Before I go further, you must realize that I am exploring this technology, so if I state something wrong, please call me out!

I’ve heard in a few spots that MEF is a bit like a DI Container, but it is more about application composition than dependency injection. In its most basic use case you can define exports (using the “ExportAttribute”) and then define imports (using the “ImportAttribute”). We will start off with a very simple example, and then elaborate upon it a bit to show you how this works.

So let’s say that we have an interface which looks like this:

public interface IConsoleWriter
{
    void Write(string message);
}

We are simply going to use this interface to write out to the console, and if you didn’t pick up on that, then you are a tad slow. 🙂 Anyways, so we need to consume this in my application, so we are going to define a class which implements this interface:

public class RedConsoleWriter : IConsoleWriter
{
    public void Write(string message)
    {
        ConsoleColor originalColor = Console.ForegroundColor;
        try
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);    
        }
        finally
        {
            Console.ForegroundColor = originalColor;    
        }
    }
}

This particular implementation will now write out the value to the console in red! How cool! (sarcasm) Normally if we wanted to use this class, we could do something like this:

IConsoleWriter consoleWriter = new RedConsoleWriter();
consoleWriter.Write("Hello from the console!");

But we obviously are not interested in doing that here, MEF is all about extensibility, so lets make this puppy extensible. The first step that we have to take is to put an “ExportAttribute” on the “RedConsoleWriter” class to tell MEF that this is a type which we are exporting. In this attribute we will also tell MEF which type this class is exported for:

[Export(typeof(IConsoleWriter))]
public class RedConsoleWriter : IConsoleWriter
{

MEF now knows that this class is being exported for the “IConsoleWriter” interface. The next step is for us to import this guy. In order for us to do that we have to use two different classes. This is where the framework starts to feel a bit overly complex, but I’m sure as I explore it more I’ll see why this complexity was introduced.

The first class that we have to use is the “AttributedAssemblyPartCatalog“, which is a bit of a mouthful. This is one of four types of catalogs available to you. Catalogs are merely a method of gather up exports in different ways. The four types of catalogs are:

AggregatingComposablePartCatalog – Combines multiple catalogs into a single catalog. Useful if you need to gather exports in multiple different ways.

AttributedAssemblyPartCatalog – This is the one we are going to use, it takes an assembly and gathers up all types which are marked with the “ExportAttribute”

AttributedTypesPartCatalog – Looks for exports given particular types.

DirectoryPartCatalog – Watches a folder and enumerates assemblies to find exports

Next we are also going to have to use a “CompositionContainer” class, which takes a catalog and provides the ability to expose the catalog’s exports. Make sense? Let’s take a look:

private void Compose()
{        
    var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
    var container = new CompositionContainer(catalog);
    container.AddPart(this);
    container.Compose();
}

Here we are creating our catalog by passing in the current assembly, then we pass our catalog to the container constructor. The next line just passes in the current class (the “Program” class, since this is console app) to the container so that its imports will be resolved. Then we call “Compose” on our container, and that is it, our container has now been configured with all of our exports. But how do we get our exports into our application?

We do this by putting an “ImportAttribute” on the properties that we want to have “composed” by the container. So, we declare a property with the “IConsoleWriter” type, and we put the attribute on it:

[Import]
public IConsoleWriter ConsoleWriter { get; set; }

Pretty simple. Now we have to run our Program, but we have to create a new instance of our “Program” class since our property is not static. Our whole “Program” class ends up looking like this:

internal class Program
{
    [Import]
    public IConsoleWriter ConsoleWriter { get; set; }

    public static void Main(string[] args)
    {
        var p = new Program();
        p.Run();
    }

    public void Run()
    {
        Compose();
        ConsoleWriter.Write("Hello from the console!");
    }

    private void Compose()
    {        
        var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        container.AddPart(this);
        container.Compose();
    }
}

Notice that we are just using the “ConsoleWriter” property without ever assigning anything to it. By adding “this” to the container and calling composed, all “Import” attributes will be found on this type and MEF will assign a part to it. This works because we only have one export for the “IConsoleWriter” type, if we had more in this assembly then MEF would not know how to resolve it:

MEF Multiple type fail

But if we change our application to have an IEnumerable<IConsoleWriter> property, then we will get a list of all of the exported types:

internal class Program
{
    [Import]
    public IEnumerable<IConsoleWriter> ConsoleWriters { get; set; }

    public static void Main(string[] args)
    {
        var p = new Program();
        p.Run();
    }

    public void Run()
    {
        Compose();
        foreach (IConsoleWriter consoleWriter in ConsoleWriters)
        {
            consoleWriter.Write("Hello from the console!");   
        }        
    }

    private void Compose()
    {        
        var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        container.AddPart(this);
        container.Compose();
    }
}

That is pretty cool. Now we are looping through our “RedConsoleWriter” and our “BlueConsoleWriter” and writing each out to the console:

image

Neato.

Well, that was just a quick look at some of MEF’s most basic features, but in the next post I’ll take a look at some of the other catalog types and how we can use them in order to really start adding external plugins to our application. Hope you found this useful!

Download the Full Source Here

More Insights

View All