在我的应用程序的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方法在运行时不能解析?
答案 0 :(得分:3)
我发现了什么是错的,并且我认为我会在这里发布它,因为它有一个重要的教训。
简答:
在您注册了所有单件实例后,将serviceCollection.BuildServiceProvider()
推迟到,否则将无法解决它们。
答案很长:
问题实际上与asp核心DI容器(well sorta)无关。问题在于我在BuildServiceProvider
实例上调用serviceCollection
时为我提供IServiceProvider
的时间。
在我的实现中,我实现了一个ServiceLocator
模式,它包含了随核心提供的DI框架,因此我不会在其他架构层中引入额外的依赖。当我构建基于IServiceContainer
的定位器时,我会立即解析ServiceProvider
public ServiceLocator(
IServiceCollection serviceCollection)
{
_serviceCollection = serviceCollection;
_serviceProvider = _serviceCollection.BuildServiceProvider();
}
这就是问题所在的地方。ServiceProvider
创建的时间显然与Transients
和Scoped
实例无关。 但对于拥有托管生命周期的单身人士来说, 。在完成所有注册后,您需要推迟创建ServiceProviders
。
根据我的问题,ServiceLocator
是在片段之前构建的,这意味着当implementationFactory函数执行时,ServiceProvider
无法访问Singleton实例。
通过将ServiceProvider的创建推迟到我的应用程序第一次在运行时解析我的一个自定义类型来解决问题。