forty-two Random thoughts filtered through a babelfish.

Caliburn.Micro the MEFtacluar

This is post is part of my Learning Caliburn.Micro series. Here are the other posts in the rest of the series.


I was going to call this post ‘How I learned to stop worrying and love MEF.’, but I am not sure enough people would get the reference. Besides, it would put the focus too much on MEF, and not on Caliburn.Micro, which is the topic of the post.

This is the second in my series of using Caliburn.Micro for WPF applications. The first post, Caliburn.Micro – Hello World, covered an introduction to setting up a project, and the basics of view and view-model interaction. This week I am going to introduce how to make your applications more loosely coupled by leveraging MEF. As this series progresses, we will be leveraging MEF more, so I wanted to cover it early on.

Rob Eisenberg posted a MEFbootstrapper in the Support for MEF discussion on the Caliburn.Micro CodePlex site, and on his blog Caliburn.Micro Soup to Nuts Pt. 2 – Customizing The Bootstrapper. This article starts with a new project copied from the Hello World project of my last post. We then add Rob’s bootstrapper, and modify the project to demonstrate its use.

Before adding the MEF support, lets add a new interface called IShell. This will be the contract used by MEF to find our view-models. I place my contracts in a Contracts directory, but that is up to you. Here is the code to IShell. Right now, it is just a placeholder, but later on we will use for some more interesting things.

namespace HelloMef.Contracts
{
  public interface IShell
  {
  }
}

So now on to MEF. First thing we need to do when we use MEF is reference System.ComponentModel.Composition. So go ahead and add that reference. Next, we need the MEFBootStrapper. Once again all the hard work has been done by Rob. However, the one he has on his blog, and in the Caliburn.Micro discussion forum works with Silverlight, but it does not work as is with WPF. I will post my version, then explain the difference.

So here is the difference, beyond the use of regions and my own personal coding style of using a leading underscore for fields. Lines 22-28 are a little different. Here is the original version that Rob posted:

_container = CompositionHost.Initialize(
new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));

In Silverlight, MEF is initialized using CompositionHost.Initialize(), and in WPF we new up a CompositionContainer. To fix this, I just wrapped Rob’s original code in a Silverlight compile time check. While this class is not part of the Caliburn.Micro, it is first on my list for addition into a Caliburn.Micro.Contrib project.

We are almost there. Three more changes, and we will be a MEF enabled application. First, lets open up the MainViewModel.cs file. We need to add the IShell type as a base interface for the MainViewModel class. Then we need to add the MEF attribute to export the MainViewModel as type IShell. Here is the new version of MainViewModel.

Finally, open up App.xaml. Remember back in Caliburn.Micro – Hello World we started the framework by having the application class instantiate our bootstrapper class on start up. We need to change the name of the bootstrapper class from HelloWorldBootStrapper to MefBootStrapper. Here is the new App.xaml:

That’s it. We are done. Build and run the application and you should see the familiar program we did in the last post. The difference is that our coupling has been reduced so that the framework can now find our main view model by the contract IShell, and from there it can start our application. Over the next few posts we will add logging support, multiple views, third-party controls, and maybe a surprise or two. So stay tuned.

As a reminder, all of the source code for this project is located in my Github Learning Caliburn.Micro repository for this project.