Sunday, April 22, 2012

Using MEF in Metro-style applications

Update 23 Aug 2012:

Since I originally wrote this post the standard .Net framework MEF implementation is no longer accessible from Windows 8 Windows Store applications. Instead MEF support is released out-of-band on NuGet as a specific "MEF for web and Windows Store apps" package. Once you have added this to your Windows 8 projects there is a slightly different programming model. For more information see the Microsoft.Compostion documentation.

In brief, you can set up composition with,

var configuration = new ContainerConfiguration()
        .WithAssembly(typeof(App).GetTypeInfo().Assembly);
var compositionHost = configuration.CreateContainer();
compositionHost.SatisfyImports(this);

Original post follows,  

In a slight change from talking about the Cocoon framework, today I’m going to discuss how you may use MEF (the Managed Extensibility Framework) in Windows 8 Metro-style applications. Hopefully the reason for this deviation will become clear in my next post.

What Is MEF?

I’m not going to explain MEF in detail as this has been discussed many times before and is described on MSDN. Succinctly, taken directly from the MEF CodePlex page,
The Managed Extensibility Framework (MEF) is a composition layer for .NET that improves the flexibility, maintainability and testability of large applications. MEF can be used for third-party plugin extensibility, or it can bring the benefits of a loosely-coupled plugin-like architecture to regular applications.
For Windows 8 Metro-style app developers it is the loosely-coupled architecture that is of most interest (since third-party extensibility will not be applicable to application packages delivered through the Windows Store). This allows the individual components of your application to be designed, written and tested separately. The instantiation, lifetimes and connections between components is then managed by MEF at runtime.

Using MEF in Windows 8 Metro-Style Applications

The good news is that MEF is included in the .Net base class libraries as part of the Metro-style application profile so is included in-the-box for all such applications. Unfortunately if you look at the documentation you will see references to ‘Assembly.GetExecutingAssembly()’ that is not available in the Metro-profile,

// Does not work in Metro-style applications
 
var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());

All is not lost however, as you can access the main application assembly using,

// This does work in Metro-style applications!
 
var catalog = new AssemblyCatalog(typeof(App).GetTypeInfo().Assembly);

Note that since GetTypeInfo() is an extension method on 'Type' you will have to add "using System.Reflection;" to the top of your source file. You can also reference other assemblies simply by picking a type contained in that assembly and replacing ‘App’ in the above snippet.

Therefore a more complete snippet that would find and compose all imports in the current class is,


var catalog = new AssemblyCatalog(typeof(App).GetTypeInfo().Assembly);
var compositionService = catalog.CreateCompositionService();
compositionService.SatisfyImportsOnce(this);


Summary

Hopefully this post will help anybody trying to integrate MEF with their Windows 8 Metro-style app development. Ultimately there is an ‘ApplicationCatalog’ that should allow you to generate a catalog from all assemblies within the app package however there is a known bug in the Consumer Preview bits.

2 comments:

Unknown said...

Hi,

I could not found the support for AssemblyCatalog in the latest MEF (1.0.13.0) support for Win 8.

This line does not compiles -
var catalog = new AssemblyCatalog(typeof(App).GetTypeInfo().Assembly);

Can you please inform if I am missing something.

Unknown said...

Hi Vivek,

The method for setting up composition has changed in the latest versions of MEF for Windows Store Apps.

For more information see,
http://mef.codeplex.com/documentation

Note that you can still get the assembly reference with GetTypeInfo().Assembly.

I will update the blog post.

Andy