.NET Core 2.2中的内置依赖注入框架是否不能解决依赖关系并在创建实例时自动注入实例?或者注入依赖的唯一方法是在创建新实例时显式解决它?
我正在构建一个类库项目(因此,[FromServices]属性不是我的选择),在我看来,我几乎必须在每个类的构造函数中传递IServiceProvider。
我误解了吗?
注意:代码段只是说明性的。
public class A
{
public A()
{
}
public void DoSomethingWithB()
{
var b = new B(// To resolve IConfiguration here, I need IServiceProvider. That means I will need to inject IServiceProvider in class A first. Will it go on nesting like this everywhere?);
}
}
public class B
{
private IConfiguration _config;
public B(IConfiguration config)
{
_config = config;
}
public void DoWork()
{
// Use _config here.
}
}
答案 0 :(得分:2)
您应该使用B
方法在服务提供者中注册服务ConfigureServices
。然后,您可以使用常规构造函数注入将服务B
注入服务A
中。例如:
public void ConfigureService(IServiceCollection services)
{
services.AddSingleton<B>();
// Other stuff..
}
public class A
{
private readonly B _b;
public A(B b)
{
_b = b;
}
// Use service B in your methods...
}
public class B
{
private IConfiguration _config;
public B(IConfiguration config)
{
_config = config;
}
}
您可以根据需要创建更深的嵌套级别。例如,您也可以将服务A
添加到依赖项容器中(使用services.AddSingleton<A>
()),然后注入服务A
(这将自动注入服务B
,依此类推,等)添加到另一个服务或控制器中。
答案 1 :(得分:2)
您的类库项目完全不应该了解依赖项注入。相反,您应该做的是确保每个类在构造函数中都接受其所有依赖项,如下所示:
public void MyClass(IMyDependency dependency)
它对于称为Composition Root
的东西起作用,以确保从头开始解决所有问题。例如。对于ASP.NET,框架本身将调用Resolve
以获取Controller
并组成对象的整个树,其中您的类将直接或间接依赖于控制器。 / p>
该原则的名称叫“好莱坞原则”:请不要给我们打电话,我们给您打电话。如果您自己解决依赖关系(即“调用它们”),那么您正在做的事情称为Service Locator
,它被认为是反模式。因此,相反,您依靠的是某个人(即“他们叫您”)会在某个初始入口点向您的班级注入正确的依赖关系。
此外,任何了解DI容器的类库设计都将在将来导致许多问题,例如:做单元测试,更换DI容器等。所以最好的选择是对那里的容器一无所知。
P.S。当Microsoft将大量库与DI容器(IServiceCollection
)捆绑在一起时,Microsoft本身实际上犯了一个错误。例如。日志库,HTTP工厂等都依赖于此DI容器来完成这项工作,从而几乎不可能切换到另一个容器。
我了解这会使某人使用它变得非常容易,而又不会太了解DI,但是从长远来看,它确实会限制您的工作,例如单元测试很麻烦。