我有从同一个接口派生的服务
public interface IService { } public class ServiceA : IService { } public class ServiceB : IService { } public class ServiceC : IService { }
通常,其他诸如Unity的IOC容器允许您通过区分它们的某些Key注册具体的实现.
在Asp.Net Core中如何注册这些服务,并在运行时根据一些关键点解决它们?
我没有看到任何Add Service方法采用通常用于区分具体实现的key或name参数.
public void ConfigureServices(IServiceCollection services) { // How do I register services here of the same interface } public MyController:Controller { public void DoSomeThing(string key) { // How do get service based on key } }
工厂模式是唯一的选择吗?
UPDATE1
我已经通过了文章here,显示了如何使用工厂模式来获取服务实例,当我们有多个混合实现.但是还没有完全解决.当我调用_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,因为工厂增加了客户端被迫依赖于details here的依赖关系
解决方法
它不受Microsoft.Extensions.DependencyInjection的支持.
但是您可以插入另一个依赖注入机制,如StructureMap See it’s Home page,它是GitHub Project.
这不难:
>在project.json中添加一个依赖关系到StructureMap:
"Structuremap.Microsoft.DependencyInjection" : "1.0.1",
>将其注入到配置服务中的ASP.NET管道中,并注册您的类(see docs)
public IServiceProvider ConfigureServices(IServiceCollection services) // returns IServiceProvider ! { // Add framework services. services.AddMvc(); services.AddWhatever(); //using StructureMap; var container = new Container(); container.Configure(config => { // Register stuff in container,using the StructureMap APIs... config.For<IPet>().Add(new Cat("CatA")).Named("A"); config.For<IPet>().Add(new Cat("CatB")).Named("B"); config.For<IPet>().Use("A"); // Optionally set a default config.Populate(services); }); return container.GetInstance<IServiceProvider>(); }
>然后,要获取命名实例,您需要请求IContainer
public class HomeController : Controller { public HomeController(IContainer injectedContainer) { var myPet = injectedContainer.GetInstance<IPet>("B"); string name = myPet.Name; // Returns "CatB"
而已.
对于要构建的示例,您需要
public interface IPet { string Name { get; set; } } public class Cat : IPet { public Cat(string name) { Name = name; } public string Name {get; set; } }