我有从同一个接口派生的服务
- 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; }
- }