c# - ApplicationServices(根)IServiceProvider 和注入(inject)的 IServiceProvider 有什么区别?

标签 c# asp.net-core dependency-injection

我很难理解为什么在使用 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 . spapp.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/

相关文章:

grails - 将服务注入(inject) src/groovy 类的实例

c# - 对 ISet 集合的 Linq 查询

c# - Universal Windows App的水平StackPanel ScrollView

c# - SignInManager.PasswordSignInAsync() 成功,但 User.Identity.IsAuthenticated 为 false

asp.net-mvc - .NET Core 反射 - 如何在 ASP.NET Core 3 Razor View 中查找属性的引用?

java - 启用 spring aop 回避依赖注入(inject)

javascript - Javascript/TypeScript 中的 Azure 函数 : How to DI?

c# - 如果只需要读取一次,则在查找后从 C# 字典中删除项目的任何性能优势

c# - 在 TPL 任务中包装 .NET Remoting 异步方法

javascript - ASP.NET Core SPA 中基于 JWT 的身份验证 - 前端验证