The managed extensibility framework (MEF)
Let’s get this right out of the way right from the start, the Managed Extensibility Framework is not an Inversion of Control framework although it uses parts of Dependency Injection to fulfill its purpose; to dynamically compose applications with the help of runtime discoverability.
The Managed Extensibility Framework (MEF) is a new library in .NET that enables greater reuse of applications and components. Using MEF, .NET applications can make the shift from being statically compiled to dynamically composed. If you are building extensible applications, extensible frameworks and application extensions, then MEF is for you.
IoC frameworks are used for internal decoupling of components in your application and offer help on life-cycle management, scoping control and so on. MEF on the other hand is focused on helping you to dynamically insert new functionality into your application. Think of MEF as a form of an add-in framework which helps you compose the final application dynamically, a way to add extensibility points in your application with just a couple of lines of code, literally.
In fact the way I see it, MEF and IoC frameworks play very well together and I see myself using both at the same time quite often. Ayende wrote a good post on the difference between the two, so if you are still unsure how the two differ.
So how does it work?
Structurally speaking, the managed extensibility framework is quite straight forward and it relies on attribute-based metadata to function. The three main citizens in the MEF core is comprised of Parts, Catalogs and Containers.
Parts
There is a bit of ambiguity in the framework related to the purpose of a part (or composable part as their full name is). A part is the name given to both components of code which expose themselves to being extended by the framework, as well s the components which are used to extend the applications.
Parts can either be defined at a property or parameter level (even constructor parameters) and you use the Export and Import attributes to tell the framework how components in your application are to be used by it.
Catalogs
The purpose of catalogs are to identify and keep records of the composable parts which are available. There are many different default catalogs shipped with the current bits of the framework, for example the AttributedAssemblyPartCatalog which inspects a loaded assembly for parts and the DirectoryPartCatalog which inspects all the files inside a directory and can be configured to automatically detect if new files are added to the directory, thus supporting a scenario where an extension can be discovered, at runtime, if a new file is dropped into the folder and automatically enable your application to consume it (unfortunately it doesn’t enable you to monitor sub directories which is a major design flaw and a I hope it will be resolved in a later release).
Containers
These sit in between the parts and catalogs and helps to figure out which part goes where, so this is the real work horse of the framework
Enough! Give me code!
The first thing you are going to need is to download, and unpack, the latest version of the framework which, at the time of this writing, is the MEF Preview 2 Refresh release. To MEF enable an application you need to add a reference to the System.ComponentModel.Composition assembly which can be found in thee /bin folder of the release.
Once you have that in place, you are ready to tackle the almighty MEF HelloWorld application!
1: using System;
2: using System.Reflection;
3: using System.ComponentModel.Composition;
4:
5: class Program
6: {7: static void Main(string[] args)
8: {9: Program p =
10: new Program();
11:
12: // Wire up MEF so it can help us out with
13: // hooking up Imports with the appropriate
14: // exports
15:
16: p.Compose();
17:
18: // Notice that we've never assigned the Service
19: // property any value, but we won't get a
20: // NullReferenceException thanks to MEF
21:
22: p.Service.SayHello();
23:
24: Console.WriteLine("Done! Press any key to quit");25: Console.ReadLine();
26: }
27:
28: [Import]
29: public IHelloWorldService Service { get; set; }30:
31: /// <summary>
32: /// Build the catalog and create the composition
33: /// container.
34: /// </summary>
35: void Compose()
36: {37: Assembly executing =
38: Assembly.GetExecutingAssembly();
39:
40: AttributedAssemblyPartCatalog cat =
41: new AttributedAssemblyPartCatalog(executing);
42:
43: var container =
44: new CompositionContainer(cat.CreateResolver());
45:
46: container.AddPart(this);
47: container.Compose();
48: }
49: }
This is a simple console application, it consists of one public property and a private method. The private method Compose is where we hook up the various parts of application. Basically what this will do is to inspect the current assembly to see if it can find any members decorated with the Import or Export attributes and keep a record of them. It then creates a container and tells it to compose the application (connect the imports and exports which it knows about).
The rest is straight forward, the application accesses the Service property and calls a method which is exposed by the IHelloWorldService interface. The interesting thing to take notice of is that we’ve never assigned the property a value which would mean we’d be served a NullReferenceException in a normal application (and we still can if the framework is unable to resolve a part) but since we’ve tagged it with the Import attribute we’ve told the framework that we want it to take care of assigning it a value.
So what does the IHelloWorldService interface look like?
1: /// <summary>
2: /// This is the contract for HelloWorldServices
3: /// </summary>
4: public interface IHelloWorldService
5: {6: void SayHello();
7: }
I don’t really think there is much to say about the interface to be honest, so let’s look at how we can implement this as an exported part.
1: using System;
2: using System.ComponentModel.Composition;
3:
4: /// <summary>
5: /// An implementation of the IHelloWorld contract which
6: /// will write its output to the Console.
7: /// </summary>
8: [Export(typeof(IHelloWorldService))]
9: public class ConsoleHelloWorldService : IHelloWorldService
10: {11: public void SayHello()
12: {13: Console.WriteLine("Hello World, MEF style!");14: }
15: }
This is just the standard, run of the mill, implementation of an interface, but the think to pay attention is the Export attribute which the class has been decorated with. This tells the framework that it can be used as an part that can be plugged in at any place which can import the type IHelloWorldService.
So we have a point in our code that says “hey! give me an IHelloWorldService object” and another point which says “hey! give me to anyone that wants an IHelloWorldService object” and in between the two sits MEF and orchestrates it all.
If you run this you should see the text Hello World, MEF style! appear in the console window, indicating that MEF managed to wire things up as expected and we’ve just composed an application at runtime!
I plan on writing more about MEF, because it’s really caught my attention after just a couple of hours of use, to subscribe to my feed or keep checking back for more contents and examples on how to put MEF to work!
You can download the full source code from my codeplex page.