Reputation: 53
I have a an ASP.NET MVC 5 app, I am using Structuremap 3 as the IOC.
I have an Interface which is used in multiple types through the N-Tier and I cannot find a succinct explanation of how to to map multiple types to the same interface for automatic constructor injection.
For example I have the following declarations in my registry
For<IDataContextAsync>().Use<DbGeoContext>();
For<IDataContextAsync>().Use<DbEspContext>();
When I run my app I understand the last added instance of IDataContextAsync will be the default instance used when my app creates an instance of a type that needs an IDataContextAsync as a parameter in the constructor.
So my question is how do I tell Structuremap 3 to use a specific instance of IDataContextAsync in the registry relevant to the type being created?
Thanks.
Upvotes: 0
Views: 502
Reputation: 29821
In order to distinguish between different implementations, you can use named instances (see documentation here). You register a named instance like this:
//Default instance
For<IDataContextAsync>().Use<DbGeoContext>();
For<IDataContextAsync>().Add<DbEspContext>().Named("EspContext");
Note that the Add
method registers an instance without setting it as the default, while the Use
method registers it as the default instance. As you've already realized, the last instance registered with the Use
method becomes the default instance.
In order to tell a dependee which instance should passed to the constructor, you can use the Ctor
instruction to specify constructor parameters(see documentation here):
For<IMyRepository>().Use<MyRepository>()
.Ctor<IDataContextAsync>().Named("EspContext");
which is a confusingly named shorthand for:
For<IMyRepository>().Use<MyRepository>()
.Ctor<IDataContextAsync>()
.Is(c => c.GetInstance<IDataContextAsync>("EspContext"));
Alternatively, you can skip the named parameters magic and just go straight for the concrete type with:
For<IMyRepository>().Use<MyRepository>()
.Ctor<IDataContextAsync>().Is<DbEspContext>();
Upvotes: 1