MVVMLight SimpleIoC: Design-time Error

MVVMLight SimpleIoC: Design-time Error

If you’re using the MVVMLight toolkit within your WPF project, you may have come across this error message if you’re using the SimpleIoC container to help provide design-time data when working in Blend for Visual Studio:

SimpleIoC Error: There is already a class registered for ...
SimpleIoC Error: There is already a class registered for …

Typically within your ViewModelLocator, you would have some code like this:

/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    if (ViewModelBase.IsInDesignModeStatic)
    {
        // Create design time view services and models
        SimpleIoc.Default.Register<Core.Contracts.IDataService, Services.DesignTimeDataService>();
    }
    else
    {
        // Create run time view services and models
        SimpleIoc.Default.Register<Core.Contracts.IDataService, Services.JsonDataService>();
    }

    SimpleIoc.Default.Register<MainViewModel>();
}

Where the highlighted line (11) is responsible for registering the design-time data implementation of some service with SimpleIoC. This code will execute without a problem at runtime, but at designtime Blend often encounters the error shown above.

The problem is that SimpleIoC creates a ‘Default’ singleton instance of itself when you first call it, which isn’t usually a problem at runtime, as only one ViewModelLocator is typically created. However, within Blend’s design environment, you may find that several ViewModelLocators are being created. While this isn’t generally a problem when we’re working in the designer, the SimpleIoC.Default property is shared between ALL of these ViewModelLocators. Attempting to register a type multiple times throws an exception, which is the error Blend encountered above.

The clearest fix for this problem is to simply check if the interface has already been registered before attempting to register it:

/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    if (ViewModelBase.IsInDesignModeStatic)
    {
        if (!SimpleIoc.Default.IsRegistered<Core.Contracts.IDataService>())
        {
            // Create design time view services and models
            SimpleIoc.Default.Register<Core.Contracts.IDataService, Services.DesignTimeDataService>();
        }
    }
    else
    {
        // Create run time view services and models
        SimpleIoc.Default.Register<Core.Contracts.IDataService, Services.JsonDataService>();
    }

    SimpleIoc.Default.Register<MainViewModel>();
}

If you have a number of interfaces and classes you register at this point, you arguably don’t have to perform a check on each of them. If the first interface hasn’t been registered, then it’s likely the others haven’t either.

You might argue that SimpleIoC shouldn’t throw an exception for multiple registrations, but I prefer that it does. The error is revealing, and helps illustrate that the ViewModelLocator class is being instantiated several times.

In reality, I usually replace SimpleIoC with an alternative IoC container, such as Unity. Unity appears to be more relaxed about duplicate registrations.

The MVVM Light Toolkit was v5.0.2 at the time of writing this.