我有从相同接口派生的服务。
public interface IService { }
public class ServiceA : IService { }
public class ServiceB : IService { }
public class ServiceC : IService { }
通常,其他IoC容器例如 Unity
允许您通过一些Key
区分它们的具体实现来注册。
在ASP.NET Core中,如何注册这些服务并在运行时基于某些键解析它们?
我看不到任何Add
带有key
或name
参数的Service方法,这些方法通常用于区分具体实现。
public void ConfigureServices(IServiceCollection services)
{
// How do I register services of the same interface?
}
public MyController:Controller
{
public void DoSomething(string key)
{
// How do I resolve the service by key?
}
}
工厂模式是这里唯一的选择吗?
Update1
我看过这里的文章展示了如何使用工厂模式来获得服务实例的时候,我们有多种具体实现。但是,它仍然不是一个完整的解决方案。调用_serviceProvider.GetService()
方法时,无法将数据注入构造函数。
例如考虑一下:
public class ServiceA : IService
{
private string _efConnectionString;
ServiceA(string efconnectionString)
{
_efConnecttionString = efConnectionString;
}
}
public class ServiceB : IService
{
private string _mongoConnectionString;
public ServiceB(string mongoConnectionString)
{
_mongoConnectionString = mongoConnectionString;
}
}
public class ServiceC : IService
{
private string _someOtherConnectionString
public ServiceC(string someOtherConnectionString)
{
_someOtherConnectionString = someOtherConnectionString;
}
}
如何_serviceProvider.GetService()
注入适当的连接字符串?在Unity或任何其他IoC库中,我们可以在类型注册时执行此操作。我可以使用IOption,但这将要求我注入所有设置。我无法将特定的连接字符串注入服务。
还要注意,我试图避免使用其他容器(包括Unity),因为那样的话,我还必须向新容器注册其他所有内容(例如Controllers)。
另外,使用工厂模式创建服务实例也违反了DIP,因为它增加了客户端在此处具有详细信息的依赖关系数量。
因此,我认为ASP.NET Core中的默认DI缺少两件事:
- 使用密钥注册实例的能力
- 在注册过程中将静态数据注入构造函数的能力
Update1
移至另一个问题,因为在构造函数中注入事物与确定构造哪个对象有很大不同