在我的应用程序中,有一个接口和两个子类。 两个子类已注册为服务。 我的问题是如何控制当我使用它们时要得到哪一个?
首页控制器.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();
}
}
启动.cs
services.AddScoped<ITestDI, TestDIClass1>();
services.AddScoped<ITestDI, TestDIClass2>(); // it seems like TestDIClass2 has overwrited the TestDIClass1.
有几个选项。
首先,您可以放弃自动连线并使用委托进行注册,如下所示:
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>(),
}));
在此示例中,从ActivatorUtilities
请求HomeController
。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
并从IServiceProvider
IProductService
。
还有其他可用的选项,但这些在您的情况下可能是最有可能的选项,以防您不想更改设计。
此信息是《依赖注入原则》一书的精简版。实践和模式。其中包含有关Microsoft.Extensions.DependencyInjection(MS.DI( 和大约 16 页关于使用多个组件。
可以注册具体的类。
public HomeController(TestDIClass2 _td)
{
this.td = _td; //
}
由于您已经注册了多个实例,因此您必须向依赖注入框架询问IEnumerable<ITestDI> _testDis;
然后你必须通过它进行迭代
foreach(var instance in _testDis)
{
instance.YourMethod();
}