Как внедрить Microsoft.Extensions.DependencyInjection.IServiceScope в класс в .NET Core

У меня проблема с введением IServiceScope в мой класс.

Моя реализация сервиса:

public class AccountService : IAccountService
{
    private readonly IConfiguration _configuration;
    private readonly IServiceScope _services;

    public AccountService(
        IConfiguration configuration,
        IServiceScope services) // <-- I can't inject this
    {
        _configuration = configuration;
        _services = services;
    }

    public async Task CreateAccount(ExternalAccount externalAccount)
    {
        (some code...)
    }
}

В startup.cs:

services.AddTransient<IAccountService, AccountService>();

Проблема в том, что после указанной выше строки происходит сбой проекта со следующей ошибкой:

Некоторые службы не могут быть созданы (Ошибка при проверке дескриптора службы ServiceType: IDS.Quickstart.Account.IAccountService Lifetime: Transient ImplementationType: IDS.Quickstart.Account.AccountService: невозможно разрешить службу для типа Microsoft.Extensions. DependencyInjection.IServiceScope 'при попытке активировать' IDS.Quickstart.Account.AccountService '.) ---> System.InvalidOperationException: Ошибка при проверке дескриптора службы' ServiceType: IDS.Quickstart.Account.IAccountService Lifetime: TransientSimplementation. Quickstart.Account.AccountService »: невозможно разрешить службу для типа« Microsoft.Extensions.DependencyInjection.IServiceScope »при попытке активировать« IDS.Quickstart.Account.AccountService ».

По какой причине мой код не работает?


person Adam Mrozek    schedule 16.05.2020    source источник
comment
Внедрить IServiceScopeFactory и использовать это для создания IServiceScope   -  person Nkosi    schedule 16.05.2020
comment
Скорее всего, это проблема XY.   -  person Nkosi    schedule 16.05.2020
comment
Да, внедренный IServiceScopeFactory работает. Вы можете ответить на мой вопрос. Я поддерживаю его. Было бы неплохо объяснить, почему нельзя ввести IServiceScope.   -  person Adam Mrozek    schedule 16.05.2020


Ответы (1)


Вместо того, чтобы вводить IServiceScope, с помощью MS.DI вы вводите IServiceProvider. MS.DI автоматически внедрит версию IServiceProvider, ограниченную текущей областью. Это означает, что ваш класс может вызывать IServiceProvider.GetService, что приведет к тем же результатам, что и при вызове IServiceScope.ServiceProvider.GetService.

Будьте осторожны с внедрением специфичных для контейнера абстракций, таких как IServiceProvider, IServiceScopeFactory или IServiceScope. Если введено в классы, которые живут за пределами вашего Composition Root, он приводит к анти-шаблону Service Locator.. У Service Locator есть несколько недостатков. Имя вашего класса AccountService заставляет меня поверить, что этот класс находится вне вашего корня композиции.

Классы, которые живут внутри Composition Root, обычно состоят исключительно из логики инфраструктуры (без бизнес-логики). Внутри корня композиции нормально иметь зависимость от контейнера DI (или его абстракций), потому что эта часть уже имеет очень сильную зависимость от этого конкретного контейнера DI.

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

person Steven    schedule 16.05.2020