How can I use Simple Injector DI container to register multiple concrete types of IShipper
interface and dynamically select them using a name
?
If I can't register multiple instances of the same type, is there a different way to do with Simple Injector?
public Setup()
{
var container = new SimpleInjector.Container();
// TODO: Registration required for two different shippers
container.Register<UPS, IShipper>();
}
public interface IShipper
{
void Ship(Product product)
}
public class UPS : IShipper { ... }
public class FedEx : IShipper { ... }
public void Ship(String shipper, Product product)
{
// TODO: Retrieve the shipper by name
var shipper = container.GetInstance<IShipper>();
shipper.Ship(product);
}
Ship("FedEx", new Product());
There are many ways of doing this, for instance you could:
IShipperFactory
that allows retrieving a IShipper
.IShipper
and delegates to the real IShipper
implementation; this works in case the Product
entity itself contains information about the shipper.that forwards the call to the proper
IShipperinternally, without exposing this
IShipper` abstraction back to the client.The documentation here gives some clues about how to create multiple registrations of the same abstraction.
Here's an example using a dispatcher:
public interface IShippingDispatcher
{
void Ship(string shipper, Product product);
}
public class ShippingDispatcher : IShippingDispatcher
{
private readonly Func<string, IShipper> factory;
public ShippingDispatcher(Func<string, IShipper> factory) { this.factory = factory; }
public void Ship(string shipper, Product product) => factory(shipper).Ship(product);
}
As an example, you can have the following setup with this:
public Setup()
{
var container = new Container();
var shippers = new Dictionary<string, InstanceProducer<IShipper>>
{
{ "FedEx", Lifestyle.Transient.CreateProducer<IShipper, FedEx>(container) },
{ "UPS", Lifestyle.Transient.CreateProducer<IShipper, UPS>(container) },
};
container.RegisterSingleton<IShippingDispatcher>(
new ShippingDispatcher(shipper => shippers[shipper].GetInstance()));
}