Live Fast, Code Hard, Die Young

The Managed Extensibility Framework is a new wonderful addition to .NET 4 and Silverlight 4. The main purpose of MEF is to handle the extensibility and plug-in capability of an application. It features a very simple and elegant method for creating objects and resolving dependencies by decorating your code with import and export attributes.

Managing and resolving dependencies and creating objects is pretty much what a simple IoC (Inversion of Control) container does. So, can we use MEF for this?

The MEF man Glenn Block once said that ”you should use MEF to manage your unknown dependencies and an IoC container to manage your known dependencies.” However, I have found that MEF can work pretty well as your one stop solution for all dependencies. It is especially nice if you are building a Silverlight application that already uses MEF (for example to download XAPs dynamically). Why include a separate third party IoC container when there is one built in already?

Here is a short guide for those who want to use MEF for dependency injection in Silverlight.

MEF libraries

First of all, you need to add a reference to the MEF libraries. They are included with Silverlight 4:

image

System.ComponentModel.Composition – You need this reference anywhere you use the basics of MEF such as importing and exporting.

System.ComponentModel.Composition.Initialization – You need this reference where you actually initialize and configure the container.

ServiceLocator class

To use MEF for resolving dependencies I have built a simple class to set things up and provide a way to create or retrieve instances. This is the code for a simple version of this class:

    public static class ServiceLocator
    {
        private static CompositionContainer _container;
        private static AggregateCatalog _catalog;

        public static void Initialize()
        {
            _catalog = new AggregateCatalog(new DeploymentCatalog());
            _container = CompositionHost.Initialize(_catalog);
        }

        public static T GetInstance<T>()
        {
            return _container.GetExportedValue<T>();
        }
    }

The Initialize() method sets up an AggregateCatalog and feeds it with a DeploymentCatalog. The AggregateCatalog can contain many MEF catalogs that are added at runtime. Using an AggregateCatalog is not absolutely necessary in this simple example but it is a preparation for loading dependencies dynamically in the future.

The DeploymentCatalog is used in Silverlight for working with XAP files. It is a very handy class for loading external XAPs if your application is split up in modules. Creating a DeploymentCatalog without any parameters will create a catalog for the main application XAP file and this will allow us to access the exported types in all the assemblies of our main XAP file.

When we call CompositionHost.Initialize() our assemblies will be scanned by MEF and all exports are discovered. We are then ready to call the GetInstance<T>() method whenever we need an instance of an exported class.

Exporting types

Traditional IoC containers often involve configuring components using either XML or registering them using code. With MEF you simply put an [Export] attribute on your class to indicate that it should be available for composition:

    [Export]
    public class Car
    {
        ...
    }

This will expose the type Car to MEF and lets you retrieve it in IoC fashion like this:

    var car = ServiceLocator.GetInstance<Car>();

Often you want to expose a certain interface that your type implements. You can do this by supplying the type in the [Export] attribute like this:

    [Export(typeof(ICar)]
    public class Car : ICar
    {
        ...
    }

The default behavior in MEF is to treat exports as singletons. That is, if you don’t specify anything to override this behavior you will only get one instance of the Car object in your application no matter how many times you call GetInstance<Car>(). Actually, if the exported type does not specify anything the default is to allow either singleton or non shared so it is up to the caller to decide what he wants.

If you want unique instances to be created every time you retrieve an instance of your type you can specify this using an extra attribute on your class:

    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class Car
    {
        ...
    }

Dependency injection

Of course an application is seldom built with only a single class. Most likely you have many parts that fit together and you want to use the IoC container to resolve everything smoothly for you using dependency injection. MEF can do this as well, but you have to decorate the constructor to use with the [ImportingConstructor] attribute:

    [Export]
    public class Car
    {
        [ImportingConstructor]
        public Car(Engine engine)
        {
        }
    }

    [Export]
    public class Engine
    {

    }

When retrieving a Car instance MEF will automatically create and inject the Engine in the constructor of the class just like an ordinary IoC container would.

All in all, those 20 lines of code is all you need to get started with MEF as an IoC container. You can now retrieve instances of your objects with injected dependencies and that’s pretty much what you need in most cases.

Conclusion

I wanted to keep this example as simple as possible and have deliberately left out topics like object lifetime, dynamically loading XAPs and so on. I am planning to write about those things in upcoming posts.

I think MEF provides a great alternative to the traditional IoC containers. It is very easy to setup and get started with. I also like the fact that all configuration sticks with the class, which makes it easy for newcomers in your project to pick things up quickly and write new components simply by looking at an existing class.

I believe MEF is going to be central in all .NET 4 development. Don’t miss out!

Advertisements

Comments on: "Using MEF as an IoC container" (4)

  1. Christian said:

    I like the GetInstance(.. method.
    How would you implement a Register(… method? TO register types dynamically without having ExportAttribute ?

    • It is possible to do it, but since MEF was not built to be an IOC container it’s not that straightforward. I would recommend that you choose a proper IOC container over MEF instead of abusing it too much 🙂

      Anyway, if you truly want to go down this path you should start looking at Composition Batch which is used for adding and removing parts of the catalog at runtime: http://mef.codeplex.com/wikipage?title=Composition%20Batch

  2. this is dangerous..to tempting to create singletons all over the show without any control.
    Singeltons means something is unique amongst all your objects..first ur database server is a singelton then the printer then what..the user?
    Singelton means global state.! global state is bad.! :
    when i create a person and a copy of that person at birth I want two babies and both babies to have their own head, legs, arms, feet, liver, heart. if head were a singelton object i would have simeese twins, with one head instead of normal twins…singletons creates simeese twins..not convinced….well singeltons can work..as can goto, global variables etc etc..but then why bother with object orientated programming if you objects are not complete and independent- just program in a plain old structured fashion..much faster and easier —-so long as the specs don’t change.!

    • With MEF you can choose if you want a singleton or not. By decorating your class with PartCreationPolicy(CreationPolicy.NonShared) you do not have to use singletons.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: