I have six implementations for the same interface registered on my DI container, like so:
services.AddScoped<IProductService, ProductService1>();
services.AddScoped<IProductService, ProductService2>();
// ...
services.AddScoped<IProductService, ProductService6>();
The controller which consumes these services has a parameter productName that I use to choose my desired service. For separation of concerns purposes, I implemented a factory class that takes this string and retrieves the requested service from the service provider. Something like this:
public string ProductController(string productName)
{
var myService = _productFactory.GetProductService(productName);
// ... do other stuff
}
This is what I had in mind for my factory class
public IProductService GetProductService(string productName)
{
switch (productName.ToLower())
{
case "product1":
return _serviceProvider.GetRequiredService<ProductService1>();
case "product2":
return _serviceProvider.GetRequiredService<ProductService2>();
// ...
}
}
However, this returns an error because it can't find the services of type ProductService1, and so forth. From my understanding of how these methods work, it only finds the type IProductService.
How can I search for a required service based on its implementation? Can I search for a service by name or is there a way to link a string to an implementation on the DI container? I don't see how a factory class would work if I couldn't tell it which implementation it should retrieve on each case.
You haven't actually registered anything as a ProductService1 or 2 or 3 etc. You registered them all as IProductService. You could just register them as the type you're trying to resolve them as, like this:
Here's a complete working example:
Note that this could actually be a bit cleaner. If you use Scrutor to do the registrations, you can stop having to register each individual type and so the next time you add a product service it will automatically get registered.
There's ways to clean up the factory and make it so you don't have to keep adding to the case statements. For example, let's say your IProductServices have to declare which product they support, we can grab them like this:
There's some other techniques that may be a bit more or less efficient or handle your scoping needs better, but I'd say that's a big improvement already.