【发布时间】:2017-05-14 16:59:42
【问题描述】:
在我的应用程序的ConfigureServices() 引导期间,我主要使用 .Net Core 附带的依赖注入框架注册瞬态和作用域类型。但是,我确实有一种注册为单例的类型是我的InProcessBus(我使用的是 CQRS 风格的架构)。
services.AddSingleton<InProcessBus>(new InProcessBus());
...
services.AddSingleton<ICommandSender>(y => y.GetService<InProcessBus>());
services.AddSingleton<IEventPublisher>(y => y.GetService<InProcessBus>());
如您所见,我正在为将在 API 控制器中使用的实际类型使用实现工厂函数。真正奇怪的是,当控制器加载并且运行时尝试构造函数注入 ICommandSender 时,它无法解决它并报告错误。
如果我检查 serviceCollection,我可以看到 implementationFactory 已针对 ImplementationInstance 属性下的类型正确注册。
深入并直接解析Startup类末尾的类型'ConfigureServices()方法确认容器正在解析null。
ServiceLocator.GetService<ICommandSender>() // Is Null
为什么针对容器中明显存在的单例的 ImplementationFactory 方法在运行时无法解析?
【问题讨论】:
-
这很奇怪。尽管您可能希望避免使用
y.GetService<T>()并使用y.GetRequiredService<T>(),如果无法解决它会抛出异常,而不是返回null。尽管这可能无法解决您的问题。还有更多吗?您也无法在ConfigureServices中解决它,当时容器尚未构建。您可以解决服务的最早一点是在Configure方法中(如果您使用模板附带的标准 Startup.cs) -
您确定要使用内置容器吗? CQRS 架构风格非常强大,因为它们使使用装饰器应用横切关注点变得非常容易。使用内置容器是不可能应用通用装饰器的。
-
@Tseng,感谢 GetRequiredService 提示,显式异常比 null 好。通常无法解决,但是当我遇到问题时,我使用 BuildServiceProvider() 来构建自己的提供程序以使用内联进行测试...
-
@Steven,我使用自定义跨框架容器合同包装容器,这样我就没有任何特定容器的硬容器依赖。这个特殊的 CQRS 实现是一个非常精简的实现,因为我实际上主要是在玩 .Net Core 和 Standard。
-
@SarelEsterhuizen:你也不会对内置有任何依赖。唯一需要参考的地方是你的作文根目录。在所有其他层中,您只需在类构造函数或
IEnumerable<T>中注入所需服务的接口,如果您需要某种类型的所有注册。 ServiceLocator 只是一个非常糟糕的模式。另请参阅下面的 cmets,您将遇到其他问题,因为您现在可能有两个容器实例,其中一个永远不会被释放。因此,如果使用不当,您的作用域服务可能会成为服务定位器中的单例
标签: .net dependency-injection asp.net-core asp.net-core-mvc .net-core