What's the difference between the ApplicationServices (root) IServiceProvider and an injected IServiceProvider?

。_饼干妹妹 提交于 2020-08-07 05:34:43

问题


I have a hard time understanding why the behaviour is different to apply the service locator pattern in the Startup Configure method when using the IApplicationBuilder.ApplicationServices in stead of IServiceProvider.

When I use IApplicationBuilder.ApplicationServices (which sets the IServiceProvider that provides access to the application's service container) I get the following error:

Cannot resolve scoped service '...' from root provider

In contrast, when I use the injected IServiceProvider directly it works like a charm:

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>();
}

Why is this? Why does the injected IServiceProvider behave like it has "service scope" and IApplicationBuilder.ApplicationServices like it has a sort of "application scope" outside of service scopes?

In a way the injected IServiceProvider works the same as creating a scope first with IApplicationBuilder and only then resolving the scoped service from the scope's service provider.

My head is spinning now.

Obviously it seems that the scope of IApplicationBuilder (does one name it like this?) is outside of service scopes. But when I look up IApplicationBuilder I can't find anything about the root provider.

Can anyone clarify this? Did I miss an obvious beginners tutorial somewhere that explains this root provider or application's service container?


回答1:


This is by design.

ASP.NET runtime instantiate IServiceProvider in such way that it prohibits scoped services resolved from the root:

serviceCollection.BuildServiceProvider(validateScopes: true);

app.ApplicationServices is root IServiceProvider. sp is child of app.ApplicationServices. You can check it using this line of code:

app.ApplicationServices == ((Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope)sp).Engine.Root
// true

So only children of app.ApplicatoinServices can resolve scoped services. One child sp was provided as input parameter, 2nd one you created manually.



来源:https://stackoverflow.com/questions/62080780/whats-the-difference-between-the-applicationservices-root-iserviceprovider-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!