C# 将IServiceProvider作为依赖项获取ASP.NET核心中的可选依赖项
将C# 将IServiceProvider作为依赖项获取ASP.NET核心中的可选依赖项,c#,asp.net-core,dependency-injection,anti-patterns,C#,Asp.net Core,Dependency Injection,Anti Patterns,将IServiceProvider注入到服务类中,作为获取ASP.NET Core 2.0中可选依赖项的一种方法,这是一种不好的做法吗?这个坏了吗 我有一个类需要一个可选服务EventBus。如果注册了EventBus,我希望服务类发布一个事件,如果不是简单地忽略它的话 public class SomeService { private readonly IServiceProvider _serviceProvider; public SomeService(IServiceP
IServiceProvider
注入到服务类中,作为获取ASP.NET Core 2.0中可选依赖项的一种方法,这是一种不好的做法吗?这个坏了吗
我有一个类需要一个可选服务EventBus。如果注册了EventBus,我希望服务类发布一个事件,如果不是简单地忽略它的话
public class SomeService {
private readonly IServiceProvider _serviceProvider;
public SomeService(IServiceProvider serviceProvider) {
_serviceProvider = serviceProvider;
}
public SomeAction() {
var eventBus = _serviceProvider.GetService(typeof(IEventBus)) as IEventBus;
if (eventBus != null) {
eventBus.publish("SomeAction Happened!");
}
}
}
我看不出如何使用ASP.NET Core 2.0的内置IoC容器创建可选依赖项
编辑:对如何在ASP.NET核心中实现可选依赖项有何建议?或任何其他策略,以在没有反模式的情况下获得相同的效果?如果该方法直接要求该策略才能正确运行,则该策略将不被视为可选策略 它应该作为依赖项显式注入
public class SomeService {
private readonly IEventBus eventBus;
public SomeService(IEventBus eventBus) {
this.eventBus = eventBus;
}
public SomeAction() {
if (eventBus != null) {
eventBus.publish("SomeAction Happened!");
}
//...
}
}
public SomeAction(IEventBus eventBus = null) {
if (eventBus != null) {
eventBus.publish("SomeAction Happened!");
}
//...
}
< P>考虑将它作为可选的依赖项显式传递给方法
public class SomeService {
private readonly IEventBus eventBus;
public SomeService(IEventBus eventBus) {
this.eventBus = eventBus;
}
public SomeAction() {
if (eventBus != null) {
eventBus.publish("SomeAction Happened!");
}
//...
}
}
public SomeAction(IEventBus eventBus = null) {
if (eventBus != null) {
eventBus.publish("SomeAction Happened!");
}
//...
}
显式依赖原则规定:
方法和类应明确要求(通常通过方法参数或
构造函数参数)他们需要的任何协作对象
要正确运行
重点矿山
注入
IServiceProvider
被认为是一种反模式,因为它遵循服务定位器模式
有一些例外情况,例如,如果依赖类也被用作工厂。注入
IServiceProvider
是。防止这样做。依赖性也不应该被忽略。这就带来了复杂性。相反,使用。使依赖性成为必需的,简化了使用者及其测试
换句话说,SomeService
应该如下所示:
public class SomeService {
private readonly IEventBus _bus;
public SomeService(IEventBus bus) {
_bus = bus ?? throw new ArgumentNullException(nameof(bus));
}
public SomeAction() {
eventBus.publish("SomeAction Happened!");
}
}
在您的应用程序中,如果不存在真正的实现,您将使用NullEventBus
实现。这应该很容易做到:
public class NullEventBus : IEventBus
{
public void publish(string message) {
// do nothing.
}
}
由于此实现不起任何作用,因此可以将其注入所有消费者。这称为服务定位器,是的,这是一种您应该避免的反模式