【发布时间】:2020-05-29 07:26:20
【问题描述】:
当使用IApplicationBuilder.ApplicationServices 而不是IServiceProvider 时,我很难理解为什么在启动配置方法中应用服务定位器模式的行为会有所不同。
当我使用IApplicationBuilder.ApplicationServices(设置提供对应用程序的服务容器访问权限的IServiceProvider)时,我收到以下错误:
无法从根提供商解析范围服务“...”
相比之下,当我直接使用 injected 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>();
}
这是为什么呢?为什么注入的IServiceProvider 表现得像是具有“服务范围”而IApplicationBuilder.ApplicationServices 表现得像是具有服务范围之外的某种“应用范围”?
在某种程度上注入的IServiceProvider 的工作方式与首先使用IApplicationBuilder 创建一个范围,然后才从范围的服务提供者解析范围内的服务相同。
我现在头晕目眩。
显然IApplicationBuilder 的范围(有人这样命名吗?)似乎超出了服务范围。但是当我查找 IApplicationBuilder 时,我找不到任何关于根提供程序的信息。
谁能澄清这一点?我是否错过了一个明显的初学者教程来解释这个根提供程序或应用程序的服务容器?
【问题讨论】:
-
你是如何注册你的
IMyScopedService的? -
我猜想为 Configure() 创建了一个作用域,而 IServiceProvider 引用了它
-
也许,但他定义了对象的生命周期?
-
@Nenad 在 Configureservices 中注册为:services.AddScoped
(); -
我发现你表现出的行为非常奇怪。
Configure方法是Startup的一部分,并且只调用一次。因此,我认为这种方法类似于“单例”。.ApplicationServices是根容器这一事实加强了这个想法。因此,我希望 only 单例可以注入到Configure,并且注入的IServiceProvider也将是根。考虑到注入的IServiceProvider被处理掉了,这可能不是bug;但这肯定是我不喜欢从我的 DI 容器中看到的行为。
标签: c# asp.net-core dependency-injection