Click here to Skip to main content
Click here to Skip to main content
Go to top

Implementing MVVM Light with Structure Map

, 9 Dec 2011
Rate this:
Please Sign up or sign in to vote.
This article is about implementing an MVVM Light based solution with an IoC container other than the built-in SimpleIoC container included in the MVVM Light framework.

Introduction

This article is about implementing an MVVM Light based solution with an IoC container other than the built-in SimpleIoC container included in the MVVM Light framework.

The MVVM Light 4.0 release implements a built-in IoC container and adapter supporting the Common Service Locator library, leaving the developer free to use whatever IoC container or service locator with the proper adapter, but there is not a demo showing how to do it, this article pretends to show how to do it in the simplest way.

Building the Code

The first step is to chose the IoC container, in this article, MVVM Light will be implemented with a Structure Map IoC container. Why this one? There is not a specific reason to use this container, it was just picked randomly, the only criteria for this article was the IoC container must support a Fluent configuration interface. The StructureMap and the adapter binaries are included in the source code.

The Common Service Locator library contains a shared interface IServiceLocator supporting an abstraction over IoC containers and service locators. This shared interface supports adapters for:

  • Castle Windsor
  • Spring .NET
  • Unity
  • StructureMap
  • Autofac
  • MEF
  • LinFu

Then it is necessary to create a new MVVM Light project named "DemoStructureMapMVVMLight" (in this article, the chosen template was MVVMLight(WPF4)), and add a new folder named "Lib" containing the files:

  • StructureMap.dll
  • StructureMapAdapter.dll

Add a reference to these files. By default, the framework profile is ".NET Framework 4.0 Client", change the profile to ".NET Framework 4.0".

Your project tree must look like this:

There is at least a couple of ways to insert the new IoC container in MVVM Light, the simplest way is to modify the ViewModelLocator. In this case, a new class SMViewLocator will be created, then delete ViewModelLocator. The new class is defined like this:

using DemoStructureMap.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using StructureMap;
using StructureMap.Configuration.DSL;
using StructureMap.ServiceLocatorAdapter;
using System.Reflection;

namespace DemoStructureMap.ViewModel
{
    /// <span class="code-SummaryComment"><summary>
</span>    /// This class contains static references to all the view models in the
    /// application and provides an entry point for the bindings.
    /// <span class="code-SummaryComment"><para>
</span>    /// Use the <span class="code-SummaryComment"><strong>mvvmlocatorproperty</strong> snippet to add ViewModels
</span>    /// to this locator.
    /// <span class="code-SummaryComment"></para>
</span>    /// <span class="code-SummaryComment"><para>
</span>    /// See http://www.galasoft.ch/mvvm/getstarted
    /// <span class="code-SummaryComment"></para>
</span>    /// <span class="code-SummaryComment"></summary>
</span>    public class SMViewModelLocator
    {
    }
}

The first thing to do is to configure the container, this logic depends on the implemented container; in the case of a container like Unity, the configuration is done by an XML file, in this case, the configuration is done by code. The configuration function will return an instance of the IServiceLocator interface. This is the common shared interface in the Common Service Locator library to query the container.

The code for the function is:

private static  IServiceLocator CreateServiceLocator()
{
    Registry registry = new Registry();

    registry.ScanAssemblies().IncludeAssembly(
             Assembly.GetExecutingAssembly().FullName);

    if (ViewModelBase.IsInDesignModeStatic)
    {
        registry.ForRequestedType<IDataService>().
          TheDefaultIsConcreteType<Design.DesignDataService>();
    }
    else
    {
        registry.ForRequestedType<IDataService>().
          TheDefaultIsConcreteType<DataService>();
    }

    IContainer container = new Container(registry);

    return new StructureMapServiceLocator(container);
}

With Structure Map, there is no need to register each class in the project, the line:

registry.ScanAssemblies().IncludeAssembly(Assembly.GetExecutingAssembly().FullName);

registers all classes in the executing assembly; with the built-in default container, each class must be registered like this:

SimpleIoc.Default.Register<MainViewModel>();

Not so easy if there is a lot of models to register!!!

A new static constructor is needed to assign the newly created interface instance to the service locator:

static SMViewModelLocator()
{
    var ioc = CreateServiceLocator();
    ServiceLocator.SetLocatorProvider(() => ioc);
}

For every model in the solution, there will be a model accessor like this:

public MainViewModel Main
{
    get
    {
        return ServiceLocator.Current.GetInstance<MainViewModel>();
    }
}

And finally there is a cleanup function to execute when the main window is closed.

public static void Cleanup()
{
    //Clean up code
}

In order to use the new model locator, it just takes to change the reference in the app.config file:

<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />

into this:

<vm:SMViewModelLocator x:Key="Locator" d:IsDataSource="True" />

And in the main window, change this piece of code:

public MainWindow()
{
    InitializeComponent();
    Closing += (s, e) => ViewModelLocator.Cleanup();
}

into this one:

public MainWindow()
{
    InitializeComponent();
    Closing += (s, e) => SMViewModelLocator.Cleanup();
}

The objective was to be able to change the container, the behavior is the same:

Conclusion

With the new support for the Common Service Locator library, changing the IoC container in an MVVM Light implementation is pretty easy.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

emardini
Software Developer Fujitsu Canada
Canada Canada
No Biography provided
Follow on   Twitter

Comments and Discussions

 
QuestionMessageBox service PinmemberGeorge Swan9-Dec-11 22:58 
AnswerRe: MessageBox service Pinmemberemardini12-Dec-11 3:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140922.1 | Last Updated 9 Dec 2011
Article Copyright 2011 by emardini
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid