MEF and Unity (or any other IoC container)

Both MEF and IoC seem to address decoupling of an application but from different perspectives.  Since they are both addressing a similar problem they don’t appear to gell together.  I haven’t come across a great solution to using both tools but Glenn Block suggests a good balance in his post addressing this exact issue.  MEF is really good for extensibility and discovery so use MEF for that.  IoC is really good for internal decoupling of services and dependencies so use IoC internally.  The code example below is my implementation of this balance.

This example uses MEF from an extensible and a discoverable standpoint.  The architecture of this application will be similar to a plugin model where even internal services will be discovered at run time.  As the services are discovered they will be registered in the IoC container (Unity).  So basically MEF is used to discover services to be started up (this is the extensible part) and services as dependencies to other services (this is the discoverable part) to be registered in the container.

Here is the trivial service definition that will be discovered and registered in the container.

[Export("Register")]
[ServiceMetadata(RegistrationType=typeof(IMyService))]
public class MyService : IMyService
{
    public void DoWork(){}
}

Below is an example of how MEF discovers types. Notice the ImportMany attribute on the Registrations property. Normally the property definition would look like public IEnumerable<object> Registrations { get; set; }. However, using the Lazy object allows us to specify a metadata type, specifically strongly typed metadata. In this case IServiceMetadata allows access to the contract type of the service were importing that was specified with the ServiceMetadata attribute on MyService. See below for the implementation of this attribute. Metadata is available without creating your own metadata attribute but it will not be strongly typed. The ContainerRegistrations class is resolved by the container and thus is injected with an instance of the container. The DirectoryCatalog directs MEF to look in the directory specified for assemblies that contain classes marked with the Export attribute. The CompositionContainer.ComposeParts(this) tells MEF to actually go out and find the services to import. Once the services are imported (via the Registrations property) each service is registered in the container using the interface specified via the metadata.

public class ContainerRegistrations
{
    private readonly IUnityContainer container;
    private IEnumerable<Lazy<object, IServiceMetadata>> registrations;

    public ContainerRegistrations(IUnityContainer container)
    {
        this.container = container;

        DirectoryCatalog catalog = new DirectoryCatalog(
            AppDomain.CurrentDomain.BaseDirectory);
        CompositionContainer compositionContainer =
            new CompositionContainer(catalog);
        compositionContainer.ComposeParts(this);
    }

    [ImportMany("Register")]
    private IEnumerable<Lazy<object, IServiceMetadata>> registrations;
    {
        get { return registrations; }
        set
        {
            registrations = value;

            registrations.ToList()
                .ForEach(
                     r => container.RegisterType(r.Metadata.RegistrationType, r.Value.GetType()));
        }
    }
}

How does MEF know which service types to use? The Import and ImportMany attributes allow the specification of both a name and type. In this above case, I chose to go after services with a name defined as “Register”. Any services marked as Export(“Register”) will be imported. Alternatively a type can be specified alone or in addition to a name.

Below is how to create strongly typed metadata. This attribute can be placed on your service as it is in the MyService implementation above.

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ServiceMetadataAttribute :
	ExportAttribute, IServiceMetadata
{
    public Type RegistrationType { get; set; }

    public string Name { get; set; }
}

Most of this code was typed in, not copied and pasted from VS so take note if there is a typo or two.

This wasn’t intended to be an intro on MEF so I glazed over those details. See the MEF site on codeplex for details.

Advertisements

One thought on “MEF and Unity (or any other IoC container)

  1. Whats up are using WordPress for your site platform? I’m new to
    the blog world but I’m trying to get started and set up
    my own. Do you require any html coding knowledge to make your own blog?
    Any help would be really appreciated!

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