Saturday, August 22, 2009

Improved MEF + Unity Integration Layer

In my last post about Managed Extensibility Framework and Unity DI container I proposed a solution to make both frameworks work together in tandem, which in turn lets the developer leverage all the features from them at the same time. Now, the improved version is out, and it's a part of the MEFContrib project!

Having learned from developing the previous version, I decided to reimplement the integration layer from the ground up. The API changed very little, though ;)

The "biggest" change since the initial version is that you no longer need to provide boolean parameter during component registration in Unity to say that you want the component to be available to MEF. Now, this is done automatically using Unity container extension. So, the initialization of the layer now is super easy as it requires only single line of code :) Consider this:

The first call to RegisterCatalog method does the initialization - under the hoods, ComposiotionContainer is created, and a link between it and Unity is established. Pretty easy, huh ? :)

Next, all the types are public, so for example, if the standard RegisterCatalog method doesn't fit your needs, you can easily create your own using all the provided types as building blocks. The one concrete use case that comes to my mind is that the current implementation of the RegisterCatalog method does not allow you to attach any additional export providers (your own root CompositionContainer for instance) to the underlying CompositionContainer. In such a case, you can easily create separate method which accepts export providers and initializes the layer. Investigating RegisterCatalog method might be beneficial :)

One neat implication of having all types public is that you can now establish one-way synchronization, being MEF to Unity, in which Unity container knows about MEF parts and can resolve them, and Unity to MEF, in which MEF can pull Unity's components.

Finally, I've added support for closed generics, i.e. you can pull components from Unity and MEF using generics.

The type 'MefContrib.Integration.Unity.CompositionIntegration' cannot be used as type parameter 'TExtension' in the generic type or method 'Microsoft.Practices.Unity.UnityContainerBase.AddNewExtension < TExtension > ()'. There is no implicit reference conversion from 'MefContrib.Integration.Unity.CompositionIntegration' to 'Microsoft.Practices.Unity.UnityContainerExtension'.

Error 2 The type 'Microsoft.Practices.Unity.UnityContainerExtension' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=null'.

The type 'MefContrib.Integration.Unity.CompositionIntegration' cannot be used as type parameter 'TConfigurator' in the generic type or method 'Microsoft.Practices.Unity.UnityContainerBase.Configure < TConfigurator > ()'. There is no implicit reference conversion from 'MefContrib.Integration.Unity.CompositionIntegration' to 'Microsoft.Practices.Unity.IUnityContainerExtensionConfigurator'.

@SimonThank you for spotting both bugs. I have updated the MEF + Unity integration layer, and even included your tests :) However, the MEF Contrib project is not yet updated to reflect these changes (the official release is coming soon, so stay tuned). You can find the changes in my own MEF Contrib release (unofficial) available at my Code Gallery.

I'm going to elaborate on the changes in the coming post about MEF Contrib 0.8, for now please see test units (I had to modify them a little to support new functionality).

Finally, I would point out that although title of this post suggests this is SL only release, it contains both .NET 3.5 and Silverlight 3 code.

This time it is a problem of multiple instanciation :When you create a ChildContainer and enable composition on it, you re-register your build strategies, causing objects to be double-instanciated (and triple if you create a new child container from the first one).

I fixed it on my private version, but did not write a UnitTest to validate it, by modifying the EnableCompositionIntegration extension method, and the constructor of CompositionIntegration to put a flag to indicate if BuildupStrategies should be registered.

Does anyone know if its possible to use a UnityConfigurationSection in conjunction with this? I'd like to inject Unity components into MEF and I've had some trouble getting this to work:

// doesnt work (types don't appear to get registered with MEF, injection does not work)UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");section.Containers["containerOne"].Configure(container);

// works (types do get registered with MEF, injection works)container.RegisterType();