В чем разница между ApplicationServices (root) IServiceProvider и внедренным IServiceProvider? - PullRequest
4 голосов
/ 29 мая 2020

Мне трудно понять, почему поведение отличается от применения шаблона локатора сервисов в методе настройки запуска при использовании IApplicationBuilder.ApplicationServices вместо IServiceProvider.

Когда я использую IApplicationBuilder.ApplicationServices (который устанавливает IServiceProvider, который обеспечивает доступ к сервисному контейнеру приложения ) Я получаю следующую ошибку:

Cannot resolve scoped service ' ... 'от root провайдера

Напротив, когда я использую введенный 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 - как будто он имеет своего рода «область применения» вне области действия службы?

В некотором смысле injected IServiceProvider работает так же, как сначала создание области действия с помощью IApplicationBuilder и только затем разрешение службы в области видимости от поставщика услуг области действия .

Теперь у меня кружится голова.

Очевидно, кажется, что область действия IApplicationBuilder (можно ли это так назвать?) Выходит за рамки обслуживания. Но когда я смотрю на IApplicationBuilder , я не могу найти ничего о провайдере root.

Может ли кто-нибудь прояснить это? Я где-то пропустил очевидное руководство для начинающих чем объясняется этот root контейнер услуг поставщика или приложения?

1 Ответ

4 голосов
/ 29 мая 2020

Это сделано намеренно.

ASP. NET экземпляр среды выполнения IServiceProvider таким образом, что он запрещает службы с ограниченной областью действия, разрешенные из root:

serviceCollection.BuildServiceProvider(validateScopes: true);

app.ApplicationServices - это root IServiceProvider. sp является дочерним элементом app.ApplicationServices. Вы можете проверить это с помощью этой строки кода:

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

Таким образом, только дочерние элементы app.ApplicatoinServices могут разрешать службы с заданной областью действия. Один дочерний элемент sp был указан как входной параметр, второй - вы создали вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...