This project is read-only.

Unity Integration

Author: Piotr Włodek

Introduction

Software developers usually structure application’s architecture using Inversion of Control containers like Unity, Windsor, or any other available. Using IoC containers produces clean, maintainable code, because developer is relieved from injecting various dependencies manually. Making use of dependency injection in an application is quite straightforward. In short, during initialization phase, application registers various components (with implementation hidden by an interface) in the container, like application wide services, repository access objects, views, presenters, and others. Next, the application uses the container to pull previously registered components and use them as if they were instantiated manually. What is important to note is that dependency injection pattern is known for some time and there are many great containers available, namely Unity, Castle Windsor, Autofac, Ninject, and many others.

However, when it comes to extensibility, developers usually craft their own plug-in systems, which is a time consuming operation requiring lots of test to be written, or eventually use System.Addin framework whose learning curve is unfortunately quite steep. Using Managed Extensibility Framework, developers get another tool in their arsenal. Unfortunately, although MEF and Unity can server similar purposes, they do not work together out of the box. Unity + MEF Integration Layer is the way to make them work in pair flawlessly.

Goals

Unity + MEF Integration Layer is a middle component (implemented as MefContrib.Integration.Unity.dll) that combines the strength of both frameworks and allows great extensibility. Using integration layer, developer can structure application’s backbone using Unity while leaving the extensibility part to MEF as you can see from the figure below.

UnityMefIntegration.gif

What the layer actually does is that it makes MEF components (i.e. components known to MEF) available to the Unity by automatically injecting them into Unity components (i.e. components registered in the Unity container), and vice versa. This “synchronization “ can be either one-way or two way. In the first case, Unity will know about MEF components (but MEF will know nothing about Unity), thus Unity will be able to inject MEF components into Unity ones. The opposite synchronization, in which MEF will know about Unity’s components, is also possible but is unlikely to be used. In the second scenario, both MEF and Unity know about each other, enabling both frameworks to use each other components.

Usage

Scenario 1a – Using MEF components in Unity

To make MEF components available to the Unity container, CompositionIntegration extension is used.

// Setup
var unityContainer = new UnityContainer();
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

// Add composition support for unity
unityContainer.AddNewExtension<CompositionIntegration>();
unityContainer.Configure<CompositionIntegration>().Catalogs.Add(assemblyCatalog);
After “registering” MEF catalog in the Unity, the container can now resolve components which initially were known to MEF. The only limitation is that using Unity, it is not possible to resolve a collection of MEF components. In such a scenario, an exception would be thrown.

Scenario 1b – Using Unity components in MEF

To make Unity components available to MEF, UnityExportProvider is used as shown below.

// Setup
var unityContainer = new UnityContainer();
var provider = new UnityExportProvider(unityContainer);
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(assemblyCatalog, provider);
It is important to note, that creation of UnityExportProvder should immediately follow Unity creation, because it registers a helper Unity extension that tracks all types being registered in the Unity. If a developer registers a component in the Unity before creating UnityExportProvider, that type will not be available to MEF.

Scenario 2 – Full Unity + MEF Integration

In this scenario, which probably will be used most often, both frameworks can exchange and inject components. To create “link” between Unity and MEF, a developer needs to register a catalog in the Unity by means of extension method RegisterCatalog, like in to code below.

// Setup
var unityContainer = new UnityContainer();
var aggregateCatalog = new AggregateCatalog();

// Register catalog
unityContainer.RegisterCatalog(aggregateCatalog);
After first catalog is registered in Unity, all types available in it are immediately available to Unity while all types registered in the Unity are available to MEF at the same time. It’s most common that the first catalog will be AggregateCatalog, and all subsequent catalogs are going to be added to it.

Last edited Aug 21, 2009 at 7:48 AM by TheCodeJunkie, version 4

Comments

barakbbn Mar 24, 2013 at 12:15 PM 
Does it support Open generics?
Since as far as I tried, both using unity open-generic registration:
... RegisterType(typeof(IConfiguration<>), typeof(FileBasedConfiguration<>))

and using MEFContrib open-generic solution (GenericCatalog & GenericContractRegistryBase)
it didn't work. (inject to ImportingConstructor in this case)

Without the MEF-unity integration, each open-generic solution works fine
(but without the benefits on Unity+MEF, of course)

Thanks

chuckc Mar 23, 2010 at 12:39 AM 
What is a good place to insert the MEF integration code in a typical PRISM app with it's own bootstrapper?

The following use in the ComposeMEF method seems reasonable to me, but it raises a NotSupportException with the message "The invoked member is not supported in a dynamic assembly" when the bootstrapper Run method is called.

Thanks for any guidance.

-----------------------------
internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
var view = Container.Resolve<ShellView>();
view.Show();
return view;
}

protected override void ConfigureContainer()
{
base.ConfigureContainer();

ComposeMef(); // Start PRISM/MEF integration - is this appropriate usage?
}

private void ComposeMef()
{
// Setup
var unityContainer = new UnityContainer();
var aggregateCatalog = new AggregateCatalog();

// Register catalog
unityContainer.RegisterCatalog(aggregateCatalog);
}

protected override IModuleCatalog GetModuleCatalog()
{
return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}

}

kentcb Feb 10, 2010 at 1:14 PM 
@shoerob: Unity unhelpfully uses string.Empty as the default name for type registrations rather than null. You can work around this by looping over section.Containers.Default.Types and registering the types yourself:

foreach (UnityTypeElement typeElement in section.Containers.Default.Types)
{
var lifetimeManager = (LifetimeManager)null;

if (typeElement.Lifetime != null)
{
lifetimeManager = typeElement.Lifetime.CreateLifetimeManager();
}

container.RegisterType(typeElement.Type, typeElement.MapTo, lifetimeManager);
}

shoerob Feb 2, 2010 at 5:32 PM 
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<IMyService, MyService>();