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>();
}