Introducing Caliburn.Micro.Autofac

Last year I wrote Bootstrapping Caliburn.Micro with Autofac and it has since become one of my most popular posts. While the code presented in the post worked at that time, wizbit and Craigology pointed out that it stopped working with newer versions of Autofac. I set out to do the minimum amount of changes to make it work with the newest versions Autofac and Caliburn.Micro.

The Best Laid Plans

That was the plan. It has been said that no plan survives first contact with the enemy. Once again that saying is proved true. Both Caliburn.Micro and Autofac were now available as Nuget packages. Given my ongoing goal to try and favor Nuget dependencies, I used them.{:.float_right} That’s when I discovered Caliburn.Micro’s new default bootstrapper based on MEF. While I think this is a vast improvement over the original default, and I like the fact that it is included as part of Caliburn.Micro, it broke some of my default conventions. Specifically, I like to enforce a certain project structure when working with MVVM in which views are in a Views namespace, and ViewModels are in a ViewModels namespace. My Autofac bootstrapper enforced this.

This got me thinking that while it is my convention, it might not be for others. So, I made a few changes to my bootstrapper to make this convention an option with my setting as default (it is still opinionated code). That’s when I noticed a few other settings that other users of my bootstrapper might want. Can you smell the scope creep? By the time I was done with my changes, I had created four properties that can be changed, added a new override, and decided to make this a Nuget package of its own.

So before I go on to the new stuff, where are the changes I made? Specifically, the code in GetInstance() when I tried to resolve in Autofac by name. Both wizbit and Craigology suggested fixes, but I liked Craigology’s TryResolve fix, and updated the code accordingly. So thank you to both.

Four Ways To Modify My Opinion

EnforceNamespaceConvention

/// Should the namespace convention be enforced for type registration. The default is true.
/// For views, this would require a views namespace to end with Views
/// For view-models, this would require a view models namespace to end with ViewModels
/// <remarks>Case is important as views would not match.</remarks>
/// </summary>
public bool EnforceNamespaceConvention { get; set; }

ViewModelBaseType

/// <summary>
/// The base type required for a view model
/// </summary>
public Type ViewModelBaseType { get; set; }

CreateWindowManager

/// <summary>
/// Method for creating the window manager
/// </summary>
public Func<IWindowManager> CreateWindowManager { get; set; }

CreateEventAggregator

/// <summary>
/// Method for creating the event aggregator
/// </summary>
public Func<IEventAggregator> CreateEventAggregator { get; set; }

Overrides

ConfigureBootstrapper

/// <summary>
/// Override to provide configuration prior to the Autofac configuration. You must call the base version BEFORE any 
/// other statement or the behaviour is undefined.
/// Current Defaults:
///   EnforceNamespaceConvention = true
///   ViewModelBaseType = <see cref="System.ComponentModel.INotifyPropertyChanged"/> 
///   CreateWindowManager = <see cref="Caliburn.Micro.WindowManager"/> 
///   CreateEventAggregator = <see cref="Caliburn.Micro.EventAggregator"/>
/// </summary>
protected virtual void ConfigureBootstrapper()

ConfigureContainer

/// <summary>
/// Override to include your own Autofac configuration after the framework has finished its configuration, but 
/// before the container is created.
/// </summary>
/// <param name="builder">The Autofac configuration builder.</param>
protected virtual void ConfigureContainer(ContainerBuilder builder)

How to Use Caliburn.Micro.Autofac

Using Nuget for Caliburn.Micro.Autofac

The Nuget package id is Caliburn.Micro.Autofac. So you can install the package from the Nuget package manager shell using the following command:

or if you are more GUI minded, use the Add Package Reference dialog.

Getting the Code for Caliburn.Micro.Autofac

You can find the code for Caliburn.Micro.Autofac on github at https://github.com/dbuksbaum/Caliburn.Micro.Autofac.

Configuring Your Code to use Caliburn.Micro.Autofac

Assuming you just added Caliburn.Micro using Nuget to your application, you should have a view, viewmodel, and IShell interface. If you followed the completion instructions, you will have modified the App.xaml file to reference the AppBootstrapper. If you haven’t done that, do it. Then open the AppBootstrapper.cs file. Replace the Caliburn.Micro AppBootstrapper with the following implementation.

public class AppBootstrapper : AutofacBootstrapper<ShellViewModel>
{
  protected override void ConfigureBootstrapper()
  {  //  you must call the base version first!
    base.ConfigureBootstrapper();

    //  override namespace naming convention
    EnforceNamespaceConvention = false;
    //  change our view model base type
    ViewModelBaseType = typeof(IShell);
  }
}

Then compile and run.

So what are the key differences? The base class for the bootstrapper is the AutofacBootstrapper; the type parameter is ShellViewModel instead of IShell; and we overrode ConfigureBootstrapper to tweak the conventions to support the Caliburn.Micro default case.

Summary

While this little update turned out to be more significant than expected, it gave me the opportunity to not only update the bootstrapper for the current versions of Autofac and Caliburn.Micro, it gave me an excuse add a few nice-to-have features, and to turn this into a Nuget package.

If you have suggestions of new features, please comment below or add an issue to the issue tracker.

Related

comments powered by Disqus