Unity as IoC container for Caliburn.Micro

You might have heard about Caliburn, a client framework for WPF and Silverlight. Caliburn is a very rich and featured framework, as a consequence of this the, the great programmer Rob Eisenberg have reset the full Caliburn with a new and fresh one, named Caliburn.Micro.

Caliburn.Micro is smaller, more lightweight and it has a lot of good features that I think are useful when building rich applications for WPF, Silverlight and Windows Phone 7.

Caliburn.Micro have a focus on convention, meaning that it will automate a lot of the tedious tasks you normally have to do when you’re applying design patterns such as Model-View-ViewModel (MVVM, Presentation Model). Actions (commanding) can be achieved simply by naming your ViewModel operations with the same name as your Buttons and other action-controls in the View.

This new framework can reduce the complexity of your applications and make them cleaner and more adaptable to change in the future. Reducing complexity should always be one of the top priorities when building software.

(Note: The content of this article will probably become outdated as the Caliburn.Micro documentation is updated, though at the current time this is the only known example of IoC with Caliburn.Micro)

(Note July 9th 2010: As expected, Rob Eisenberg has updated the Caliburn.Micro documentation with an bootstrapper which uses MEF. If you’re a MEF-kind-of-programmer, check it out. I would still advice on using the Common Service Locator in the bootstrapper as oppose to directly working with the MEF-types. I don’t like binding my types to a specific IoC container, which you are with the MEF-attributes on your types and properties. With some IoC frameworks, you can simply use any custom interface and have your objects injected using Dependency Injection)

Inversion of Control

Inversion of Control is a pattern which helps separate the responsibility of creating objects from the classes which uses them. This can greatly enhance the way you can build a modular application which easier supports replacing existing logic and makes testing a whole lot simpler.

To learn more about IoC, see http://msdn.microsoft.com/en-us/library/ff647976.aspx

Building Caliburn.Micro

At the present time, there is no binary release of Caliburn.Micro available. You have to download the source code and compile it yourself using Visual Studio 2010. Head on over to CodePlex to get the source, http://caliburnmicro.codeplex.com/SourceControl/list/changesets

Caliburn.Micro is released under the MIT license, which means you can basically do almost anything you want with the source, even include it in your own product which is not open source. When you open the Caliburn.Micro solution file, you’ll see three projects, one for Silverlight, one for WPF and a last one for Windows Phone 7 (WP7).

Downloading Unity

Before you can continue to add IoC support for your WPF application, you need to download your favorite IoC framework. My favorite is Autofac, but for this demo I’m using Unity which is developed by the Microsoft patterns & practices group. Get the latest release from http://unity.codeplex.com/

Creating a new WPF project

Go ahead and create a new WPF project or open any existing project you might have. First step is to add reference to the following assemblies: Caliburn.Micro, System.Windows.Interactivity (included with Caliburn.Micro and my sample download at the bottom), Microsoft.Practices.Unity and finally the Microsoft.Practices.ServiceLocation. The ServiceLocation assembly is a common service locator assembly that has been built to provide a unified interface for all IoC frameworks.

Next you should follow the example in the documentation for Caliburn.Micro, it explains how to get the basic application up and working, see http://caliburnmicro.codeplex.com/wikipage?title=Basic%20Configuration%2c%20Actions%20and%20Conventions&referringTitle=Documentation

Creating a Container

If you got your basic application up and running with an empty bootstrapper, it’s time to create your IoC container. Create a new class in your project and name it Container. Create a single method can call it Build, returning IServiceLocator (found in the Microsoft.Practices.ServiceLocation namespace). This makes it possible for you to reuse this container type across other third party libraries which happen to play nice and supports the Common Service Locator.

    public IServiceLocator Build()
    {
        IUnityContainer unity = new UnityContainer();

        // Register our services.
        unity.RegisterType<IFileService, FileService>();

        // Register all the ViewModels in our project.
        foreach (Type t in typeof(ViewModel).Assembly.GetTypes())
        {
            if (typeof(ViewModel).IsAssignableFrom(t))
            {
                unity.RegisterType(t);
            }
        }

        // Return an type which implements the Common Service Locator interface.
        UnityServiceLocator commonLocator = new UnityServiceLocator(unity);
        return commonLocator;
    }

Finishing the Bootstrapper

If you followed the example on the Caliburn.Micro site, you should have a empty bootstrapper. I called mine ClientBootstrap and it loads my ShellViewModel as the root element.

There are four operations you need to override to add your custom IoC container, they are Configure, BuildUp, GetAllInstances and GetInstance. If your Container class returns an IServiceLocator, you already have similar methods available. The only thing missing is the BuildUp. Unfortunlately there are no operation in the Common Service Locator interface for BuildUp, so either you have to revert to returning the IUnityContainer from your Build operation, or you might make it without the BuildUp override.

This is how my bootstrapper ends up looking.

    public class ClientBootstrap : Bootstrapper<ShellViewModel>
    {
        IServiceLocator _container;

        protected override void Configure()
        {
            Container container = new Container();
            _container = container.Build();
        }

        protected override void BuildUp(object instance)
        {}

        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return _container.GetAllInstances(service);
        }

        protected override object GetInstance(Type service, string key)
        {
            return _container.GetInstance(service, key);
        }
    }

Source Code

You can download the sample source code here. This sample is named “Flickr Downloadr” for the simple reason that I’m rewriting my popular photo download utility to WPF4, check out the existing version at http://flickrdownloadr.codeplex.com/


Comments

Comments are closed

Pages

Search

Tags

None

    Recent posts

    Recent comments

    Blogroll

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.