Using the Managed Extensibility Framework in a Class Library

Recently, as you might have read, I have been to the Microsoft DevDays and have seen lots of new things I just had to try. One of these things was the Managed Extensibility Framework, or MEF for short. When I saw the presentation on MEF (in a Silverlight application) given by Mike Taulty I immediately had to think on the use of MEF with the Repository Pattern.

The Managed Extensibility Framework is an easy way to make “extensible applications and components”. With other words it makes it very easy to couple different parts (forms, pages, libraries) together.

The plan was to make a three tier MVC.NET application (presentation layer, business layer and data layer) and use MEF between the Business and Data Layer. So from a library to a library, which is subsequently different from almost all examples you can currently find.

Reference

Let’s first start with the basics… To set up a situation where the different parts will find each other we are going to need to reference the framework. For this we simply need to place a reference the System.ComponentModel.Composition.dll component in every project that makes use of the framework. This component is part of the .NET 4.0 Framework but can also be downloaded from codeplex.

Exposing and Finding

The Managed Extensibility Framework uses the Import and Export attribute to let the framework know they can be coupled. Import looks for a partner and Export exposes itself as one. To make sure they look and find for the correct partner we can specify a type amongst others. Since we wanted to use MEF with the Repository Pattern, coupling on the interfaces used for this pattern is a ready-made solution.

So all repositories who want to be imported make themselves known as the interface type they are based upon:

[Export(typeof(IForumRepository))]
public class ForumRepository : IForumRepository

The business logic class that looks for these does so in a property that is thus defined with an Import looking for these interfaces, however on the import side we define a bit more. We also tell the framework that we need an interface to work (AllowDefault), that when we found a partner we don’t want another (AllowRecomposition) and that the interface we found may also be used by others looking for this interface (RequiredCreationPolicy).

[Import(typeof(IForumRepository), AllowDefault = false,
AllowRecomposition = false, RequiredCreationPolicy = CreationPolicy.Shared)]
private IForumRepository Repository { get; set; }

Coupling

Now that we have created the parts that need to be coupled we need to make them find each other. For this we need to set up a hosting for the parts. This is simply a container which contains all the exports and imports and will couple them together. However this container needs to know where to find the imports and exports.

In this example I wanted to make sure there would be no reference at all to the data layer. This should simply be a dll that can be dropped into the bin folder and thus can be easily replaced by another one for, let’s say, another database. So I wanted to find the exports in the dll’s in the bin directory. For this we use a DirectoryCatalog, which simply is a catalog of all files in a directory that might contain exports.

DirectoryCatalog catalog = new DirectoryCatalog(AssemblyDirectory, "*.dll");

Next we must declare where to look for the imports. These will be gathered in a CompositionBatch. So we have to declare one and add to it the parts in which we want to find the imports. These parts can be anything, but what is important to note is that is must be a (running) instance of it. So if we want to make a library class able to find exports, what we want, we must make sure we add the instance of that library class to this batch and not just the class.

CompositionBatch batch = new CompositionBatch();
batch.AddPart(this);

Finally we must add the catalog to the container and compose new compositions (couplings) with the use of the declared batch.

CompositionContainer container = new CompositionContainer(catalog);
container.Compose(batch);

Generic Coding

This is all easy enough and we can instance every library class that needs to import with the above code, but I just hate to write the same code over and over again. So I made a simple initialization class with a function containing the above code and call that from every class initialization (which is effectively the same).

public void Compose(object attributedPart)
{
DirectoryCatalog catalog = new DirectoryCatalog(AssemblyDirectory, "*.dll");

CompositionBatch batch = new CompositionBatch();
batch.AddPart(attributedPart);
 
CompositionContainer container = new CompositionContainer(catalog);
container.Compose(batch);
}

However there must be a better way for this: a way to have just one container for all the running instances of my classes. So if anyone can help me here, please… I will keep you updated!

Summary

The Managed Extensibility Framework is very easy to use and makes the use of plug-ins very easy. Not just plug-ins are easy, but every kind of composition is made easy with this framework. Composing the business layer to your data layer using the repository pattern is thus also a piece of cake. I for one will use the Managed Extensibility Framework extensively from now on.

Download

Everything is much easier to comprehend if you have an example to go by, so I made this one: Sample-on-Using-the-Managed-Extensibility-Framework-in-a-Class-Library.zip (1.21 mb).

I am currently making a larger application, but for the example everything else was just overhead. If you feel there is something missing though: that is correct. This is just a “simple” example of getting information from a database with the use of a repository and to pass that information on (through the use of MEF) to a simple MVC.NET web page.