Свойство ASP.Net Core 2 ServiceProviderOptions.ValidateScopes - PullRequest
0 голосов
/ 06 мая 2018

Что такое ServiceProviderOptions.ValidateScopes точно? Я чувствую, что не могу полностью понять, что он делает под капотом. Я натолкнулся на это с помощью учебника, но без объяснения.

1 Ответ

0 голосов
/ 06 мая 2018

Полагаю, вы говорите об этом куске кода:

services.BuildServiceProvider(new ServiceProviderOptions
{
    ValidateScopes = true
});
// or 
services.BuildServiceProvider(true); // or false

Базовый поставщик ASP.NET имеет механизм, который проверяет, разрешается ли служба с определенными областями в одноэлементном контейнере. ASP.NET Core имеет два вида контейнеров. Основной одноэлементный контейнер, действительный в течение срока службы приложения, и контейнеры с областями действия для каждого запроса.

Этот параметр предотвратит разрешение служб с областью действия из одноэлементного контейнера, то есть если вы случайно попытаетесь разрешить службу с областью действия в методе Configure, вы получите исключение. Принимая во внимание, что если вы отключите это, вы не должны.

public void Configure(IApplicationBuilder app)
{
    // will throw exception, since by default DbContext is registered as scope
    app.ApplicationServices.GetRequiredService<MyDbContext>();
}

Исключением является нечто похожее на

InvalidOperationException: Невозможно разрешить IExampleService от корневого поставщика, так как для него требуется служба с ограниченным доступом MyDbContext.

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

Правильный способ разрешения сервисов в пределах области действия, т. Е. Метод Configure - это

// get scoped factory
var scopedFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
// create a scope
using (var scope = scopedFactory.CreateScope())
{
    // then resolve the services and execute it
    var context = scope.ServiceProvider.GetRequiredService<MyDbContext>();
}
// here, the child (scoped) container will be disposed and all scoped and transient services from it

Значением по умолчанию является true, и вы должны оставить его таким, если вы точно не знаете, что делаете, в противном случае вы рискуете получить утечку памяти (или исключение объекта, уже имеющего исключение) из-за невыпущенных сервисов.

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