核心 MVC 中的动态依赖注入 ASP.NET



在我的应用程序中,有一个接口和两个子类。 两个子类已注册为服务。 我的问题是如何控制当我使用它们时要得到哪一个?

首页控制器.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请求HomeControllerCreateInstance调用提供了一个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并从IServiceProviderIProductService

还有其他可用的选项,但这些在您的情况下可能是最有可能的选项,以防您不想更改设计。

此信息是《依赖注入原则》一书的精简版。实践和模式。其中包含有关Microsoft.Extensions.DependencyInjection(MS.DI( 和大约 16 页关于使用多个组件

可以注册具体的类。

public HomeController(TestDIClass2 _td)
{
this.td = _td; //
}

由于您已经注册了多个实例,因此您必须向依赖注入框架询问IEnumerable<ITestDI> _testDis;

然后你必须通过它进行迭代

foreach(var instance in _testDis)
{
instance.YourMethod();
}

最新更新