Создание scope: разница между IServiceProvider и IServiceScopeFactory

105
18 января 2021, 10:00

В некотором asp.net mvc приложении (под .net core 2.1) мне понадобилось вручную cоздать scope для фоновой задачи. (Для 2.2 тоже актуально, но вроде отличий никаких нет)

И встречается мне два совершенно рабочих варианта на просторах сети, как это сделать.

Первый вариант построен на базе IServiceProvider (пример):

internal class TimedHostedService : IHostedService, IDisposable
{
    public TimedHostedService(IServiceProvider services)
    {
    }
    private async Task Test()
    {
        using (var scope = _services.CreateScope())
        {
            var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
            await mediator.Send(new Application.Test.Command());
        }
    }
}

Второй вариант построен на базе IServiceScopeFactory (пример1, пример2):

internal class TimedHostedService : IHostedService, IDisposable
{
    public TimedHostedService(IServiceScopeFactory scopeFactory)
    {
    }        
    private async Task Test()
    {
        using (var scope = _scopeFactory.CreateScope())
        {
            var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
            await mediator.Send(new Application.Test.Command());
        }
    }
    ...
}

Не совсем понимаю, в чём между ними разница, если оба делают одну и ту же работу. Это как-то связано с разными подходами в core 2.1 и core 2.2? Или Microsoft в разных подразделениях сделала близкие вещи для одного и того же?

Какой способ предпочтительнее использовать в веб-приложениях? Не знаю, по каким параметрам мерять, ну допустим быстродействие или использование оперативной памяти.

Answer 1

Если посмотреть как реализован метод CreateScope для IServiceProvider, то он реализован вот так:

return provider.GetRequiredService<IServiceScopeFactory>().CreateScope();

Так что с точки зрения выполнения разницы тут нет. Однако, есть разница с точки зрения семантики:

  • используя IServiceScopeFactory, вы явно декларируете, что будете создавать вложенные области;

  • используя IServiceProvider, вы не декларируете ничего.

Кроме того, если вдруг ваш контейнер не поддерживает IServiceScopeFactory - то вариант с явным использованием этого класса упадёт при старте (что хорошо, ибо fail fast), а вариант с IServiceProvider - будет падать при каждой попытке исполнить задачу.

READ ALSO
Книги и учебные ресурсы по Python

Книги и учебные ресурсы по Python

Рекомендуемая литература, курсы и документация по Python

109
Стиль с TargetType в App.xaml игнорируется

Стиль с TargetType в App.xaml игнорируется

В appxaml объявлен стиль:

129
Отправить Сочетания клавиш Winapi C#

Отправить Сочетания клавиш Winapi C#

Всем привет, никак не получается отправить другой программе комбинацию горячих клавиш Ctrl+0Они посылаются по очереди, но никак не вместе, есть...

98
в supervisor старые данные из базы

в supervisor старые данные из базы

воркер работает в бесконечном цикле и получает задачи из очередиПочему supervisor работает с устаревшими данными из базы? Модели со старыми данными

147