我很难理解为什么在使用 IApplicationBuilder.ApplicationServices
时,在启动配置方法中应用服务定位器模式的行为会有所不同。而不是IServiceProvider
.
当我使用 IApplicationBuilder.ApplicationServices
(设置 IServiceProvider
提供对 应用程序 的服务容器的访问)我收到以下错误:
Cannot resolve scoped service '...' from root provider
相比之下,当我使用 注入(inject)
IServiceProvider
直接它就像一个魅力:public void Configure(
IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider sp)
{
// 1 : resolving a scoped service directly from application services container
// IServiceProvider throws 'Cannot resolve scoped service from root provider'
var test1 = app.ApplicationServices.GetRequiredService<IMyScopedService>();
// 2 : works like a charm
var test2 = sp.GetRequiredService<IMyScopedService>();
// 3 : also works like a charm
var scope = app.ApplicationServices.CreateScope();
var test3 = scope.ServiceProvider.GetRequiredService<IMyScopedService>();
}
为什么是这样?为什么注入(inject)
IServiceProvider
表现得好像它具有“服务范围”和 IApplicationBuilder.ApplicationServices
就像它在服务范围之外有一种“应用范围”? 在某种程度上注入(inject)了
IServiceProvider
与首先使用 IApplicationBuilder
创建范围相同。然后才从范围的服务提供商处解析范围内的服务。我现在头晕目眩。
显然,
IApplicationBuilder
的范围似乎(有人这样命名吗?)不在服务范围之内。但是当我查找 IApplicationBuilder我找不到有关根提供程序的任何信息。任何人都可以澄清这一点吗? 我是否错过了解释此根提供程序或应用程序服务容器的明显初学者教程?
最佳答案
这是设计使然。
ASP.NET 运行时实例化 IServiceProvider
以这种方式禁止从根目录解析的范围服务:
serviceCollection.BuildServiceProvider(validateScopes: true);
app.ApplicationServices
是根IServiceProvider
. sp
是 app.ApplicationServices
的 child .您可以使用
Immediate Window
中的以下代码行检查这一点Visual Studio 的,在断点上(这样你可以直接访问内部 ServiceProviderEngineScope
):app.ApplicationServices == ((Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)sp).Engine.Root
// true
所以 app.ApplicatoinServices
的独生子女可以解析范围服务。一个 child sp
作为输入参数提供,您手动创建的第二个。更新:
我在 MVC Core
ServiceProvider
上给出了非常详细的回答和 Scope
默认行为 here .
关于c# - ApplicationServices(根)IServiceProvider 和注入(inject)的 IServiceProvider 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62080780/