Sunday, May 24, 2009

Unity + MEF Integration Layer

In this post, I’m going to discuss two of probable many solutions to the problem of making use of the Managed Extensibility Framework together with Microsoft’s Unity Application Block in an enterprise application. Presented solution combines the power of both frameworks, and exposes an intuitive and easy to use interface. If you are interested in putting MEF together with Unity, this post is definitely 4U. If you use Unity and want to get some basic knowledge about writing extension to it, you still might want to go briefly through the code, as the provided solution is based on the Unity Container Extensions (and MEF extensions as well). This post also assumes that you have a basic idea of Dependency Injection and how it relates to the design of an application. Basics of MEF will be helpful as well.Divagations presented here are partially based on a great post titled Hosting MEF Extensions in an IoC Container by Nicholas Blumhardt, and I recommend you take a look at it before further reading this post :).

Problem

People around are sometimes/often confused about the role MEF plays in the world of the Dependency Injection – should MEF be treated as an Injection of Control solution, and thus should supersede it, or it is something else and should be used differently? Well, this is a little bit tricky question, but in what I understand, MEF is all about composition and robust components loading, thus is best suited for providing well-known extension (plug-ins) to the application, whereas IoC serves more as a backbone of an application, which is primary responsible for making all application’s internal modules work together. To sum up, MEF and Unity are very flexible and in many cases may be used interchangeably, but a general idea is that:

if you want to provide a plug-ins infrastructure so that 3rd parties were able to provide extensions for the app, use MEF (or Managed Add-in Framework + MEF if you want robust plug-in isolation :)),

if you want to structure your application’s architecture, use modules that are decoupled but with the ability to communicate, etc., use Unity or any existing IoC.

Solution 1

The first solution is pretty easy – simply use both frameworks independently of each other.

The definite plus of this approach is its ease of putting it into action in the application. But it has some drawbacks, mainly that MEF and Unity components can’t make use of each other. In other words, MEF component cannot contain any dependencies on Unity components that can be automatically satisfied via dependency injection. The same holds true for the Unity components, they simply cannot have dependencies on MEF components (note that by MEF component I mean component initially instantiated by MEF, and by Unity component I mean a component initially created by Unity container). Another drawback is that unity does know nothing about MEF, and vice versa. And why is that important ? Consider the following sample showing a dummy Presentation Model in presenter first approach (a typical scenario):

Note that in the constructor, I have both Unity service and MEF component, and because the MyViewPresentationModel class is instantiated via Unity and Unity knows nothing about IMefComponent1, this won’t work. But it should! Argh...

Although this solution is fairly simple to implement, it has several drawbacks that makes using it painful. So let’s go to the second :)

Solution 2

This solution uses a middle component, Unity + MEF Integration Layer (implemented as Unity.Integration.Mef.dll), which allows full interoperability between Unity and MEF, as you can see from the following figure.

As you can see, Unity is the backbone component, that uses the integration layer to communicate with MEF. In this solution, Unity components may have dependencies on MEF components, and vice versa. Of course, all dependencies will by injected automatically! So the following code will work (ICoreService is a Unity service whereas IMefService is instantiated by MEF):

public class CoreService2 : ICoreService{public CoreService2(){}

[Import("MefService3")]private IMefService m_MefService3;

public void Foo(){}}

What's even more important, with this approach, it's possible to mix components in the constructors, so the following both classes will work as well. Please note, that if you have a MEF component exported by name, you can reference it using the Unity's DependencyAttribute, and if you have a Unity component registered using a name, you can reference it in a MEF component using MEF's ImportAttribute ! :)

The public interface is defined using extension methods on the IUnityContainer interface. There are two thing you have to do. Firstly, register all the MEF's catalogs in the Unity. Secondly, register the types in the Unity as you normally do. Note, however, that in order to make a type registered in the Unity container available to MEF, you must register it with an overloaded Register(Type|Instance) method that accepts a boolean as the last parameter. If it is true, registered type/instance will be available to MEF.Sometimes you will want to suppress MEF injections into Unity created instances. Why? Because it costs you a CPU cycles (believe me, lots of them!). This is where PartNotComposableAttribute attribute comes in. Just mark a class with it, and when an instance from the Unity is returned, no MEF's imports will be satisfied, conserving CPU time. This is particularly useful for presenters.

Limitations

For now, MEF components can have Unity dependencies resolved only via constructor injection, so method injection on MEF components currently won't work.

Implementation details

The implementation is rather straightforward. It uses two Unity extensions and one custom MEF ExportProvider. As stated before, public interface is delivered as a set of extension methods on the IUnityContainer interface. I've also considered deriving directly from UnityContainer class, but the former approach (the one I've chosen) appears better suited for me. What do You think ? You can leave a comment on that :)

Conclusion

The idea of bringing the power of both frameworks is very tempting. And provided solution, although definitely not the only one, seems like a good one. The code + tests (NUnit 2.5) + demo app is available on my code gallery. Hope you like it!

UpdateI've reimplemented most of the layer from the ground up, now it's a part of the MEFContrib project. Please see my post about it here.