Fork me on GitHub

Registering a Single Instance Against Multiple PluginTypes Edit on GitHub


It's not uncommon to want a single instance registration in StructureMap to be mapped to multiple plugin type interfaces, especially if you have a class that implements multiple role interfaces to support different consumers.

As a simplified example, let's say that we have a class named StatefulCache that will govern some kind of application wide state. Some consumers will only need to read or query data, so we'll create an IReader interface for that role. Other consumers will only make updates to the StatefulCache, so we'll also have an IWriter interface as shown below:


public interface IWriter { }

public interface IReader { }

public class StatefulCache : IReader, IWriter
{
}


What we need from StructureMap is a way to make all requests to either IReader and IWriter resolve to the same singleton object instance of StatefulCache.

StructureMap provides the Forward<TFrom, TTo>() mechanism for exactly this purpose:


[Fact]
public void stateful_cache_serves_multiple_interfaces()
{
    var container = new Container(_ =>
    {
        // Let's make StatefulCache a SingletonThing in the container
        _.ForConcreteType<StatefulCache>().Configure.Singleton();

        _.Forward<StatefulCache, IReader>();
        _.Forward<StatefulCache, IWriter>();
    });

    container.GetInstance<IReader>().ShouldBeOfType<StatefulCache>();
    container.GetInstance<IWriter>().ShouldBeOfType<StatefulCache>();
}


And because the syntax has consistently been confusing to users (including me even though I wrote it), here's how to effect the same registration with lambda registrations:


[Fact]
public void equivalent()
{
    var container = new Container(_ =>
    {
        // Let's make StatefulCache a SingletonThing in the container
        _.ForConcreteType<StatefulCache>().Configure.Singleton();

        _.For<IReader>().Use(c => c.GetInstance<StatefulCache>());
        _.For<IWriter>().Use(c => c.GetInstance<StatefulCache>());
    });

    container.GetInstance<IReader>().ShouldBeOfType<StatefulCache>();
    container.GetInstance<IWriter>().ShouldBeOfType<StatefulCache>();
}