在我的应用中,有一个接口和两个子类。 两个子类已注册为服务。 我的问题是当我使用它们时如何控制获得哪一个?
HomeController.cs
public class HomeController : Controller
{
public interface ITestDI
{
}
public class TestDIClass1: ITestDI
{
public TestDIClass1()
{
}
}
public class TestDIClass2 : ITestDI
{
public TestDIClass2()
{
}
}
ITestDI td;
public HomeController(ITestDI _td)
{
this.td = _td; // how to control which ITestDI implementation will injected with constructor injection? With the configuration below, always get TestDIClass2.
}
public IActionResult Index()
{
return View();
}
}
Startup.cs
services.AddScoped<ITestDI, TestDIClass1>();
services.AddScoped<ITestDI, TestDIClass2>(); // it seems like TestDIClass2 has overwrited the TestDIClass1.
答案 0 :(得分:1)
有一些选择。
首先,您可以放弃自动布线并使用委托进行注册,如下所示:
services.AddScoped<TestDIClass1>();
services.AddScoped<TestDIClass2>();
services.AddTransient<HomeController>(c => new HomeController(
_td: c.GetRequiredService<TestDIClass2>());
在这里,您要按其具体类型注册两个ITestDI
。这允许HomeController
的委托人使用GetRequiredService<T>
请求特定的实现。
手动连接此类对象会变得很麻烦,尤其是在HomeController
包含更多依赖项的情况下,因为这将需要您手动解析所有 项依赖项。因此,您可以使用MS.DI的ActivatorUtilities.CreateInstance
类。它实现了MS.DI的自动装配功能的简化形式。以下代码片段显示了这一点:
services.AddScoped<TestDIClass1>();
services.AddScoped<TestDIClass2>();
services.AddTransient<HomeController>(c =>
ActivatorUtilities.CreateInstance<HomeController>(
c,
new object[]
{
c.GetRequiredService<TestDIClass2>(),
}));
在此示例中,从HomeController
请求了ActivatorUtilities
。向CreateInstance
调用提供了一个IServiceProvider
实例(c
参数)和一个实例数组,以注入到HomeController
的构造函数中。 ActivatorUtilities
将提供的对象与HomeController
的构造函数参数匹配,并将解析提供的IServiceProvider
中所有缺少的参数。
使用ActivatorUtilities.CreateInstance
可使您的注册保持不变,即使将新参数添加到HomeController
的构造函数中,例如:
public HomeController(
ILogger logger, // new argument added
ITestDI td,
IProductService service // another argument added
)
ActivatorUtilities.CreateInstance
将指出,已解析的TestDIClass2
可映射到td
构造函数参数,它将从{解析ILogger
和IProductService
{1}}。
还有其他可用选项,但是如果您不想更改设计,这些可能是您最有可能的选项。
此信息是尚未发行的书籍Dependency Injection in .NET, 2nd edition的精简版。其中包含有关Microsoft.Extensions.DependencyInjection(MS.DI)的完整章节,以及有关使用多个组件的大约16页。该章的预发行版本已经可以下载。
答案 1 :(得分:0)
可以注册具体课程。
public HomeController(TestDIClass2 _td)
{
this.td = _td; //
}
答案 2 :(得分:0)
由于您已经注册了多个实例,因此必须向Dependency Injection框架索取IEnumerable<ITestDI> _testDis;
然后您必须对其进行迭代
foreach(var instance in _testDis)
{
instance.YourMethod();
}