Получение IServiceProvider как зависимости для получения дополнительных зависимостей в ASP.NET Core - PullRequest
0 голосов
/ 18 мая 2018

Является ли плохой практикой ввод IServiceProvider в класс обслуживания в качестве средства получения необязательных зависимостей в ASP.NET Core 2.0?Разрывает ли это Явный принцип зависимости ?

У меня есть класс, которому требуется дополнительная служба, EventBus.Если EventBus зарегистрирован, я хочу, чтобы сервисный класс опубликовал событие, если не просто проигнорировал его.

public class SomeService {
   private readonly IServiceProvider _serviceProvider;

   public SomeService(IServiceProvider serviceProvider) {
      _serviceProvider = serviceProvider;
   }

   public SomeAction() {
      var eventBus = _serviceProvider.GetService(typeof(IEventBus)) as IEventBus;
      if (eventBus != null) {
           eventBus.publish("SomeAction Happened!");
      }
   }
}

Я не вижу, как создать необязательные зависимости со встроенным IoC-контейнером ASP.NET Core 2.0.

РЕДАКТИРОВАТЬ: какие-либо предложения, как реализовать необязательные зависимости в ASP.NET Core?Или любая другая стратегия, чтобы получить тот же эффект без анти-паттерна?

Ответы [ 2 ]

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

Внедрение IServiceProvider является реализацией анти-паттерна сервисного локатора *1003*.Не делайте этого.Кроме того, зависимости не должны быть необязательными .Это вводит сложность.Вместо этого используйте шаблон Null Object .Создание зависимости required упрощает потребителя и его тестирование.

Другими словами, SomeService должно выглядеть следующим образом:

public class SomeService {
   private readonly IEventBus _bus;

   public SomeService(IEventBus bus) {
      _bus = bus ?? throw new ArgumentNullException(nameof(bus));
   }

   public SomeAction() {
       eventBus.publish("SomeAction Happened!");
   }
}

В вашем Корневая композиция вы используете реализацию NullEventBus на случай, если реальной реализации не существует.Это должно быть так просто:

public class NullEventBus : IEventBus
{
    public void publish(string message) {
        // do nothing.
    }
}

Поскольку эта реализация ничего не делает, ее можно внедрить всем потребителям.

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

Это не будет считаться необязательным, если это будет требоваться непосредственно методом для правильной работы.

Он должен быть явно введен как зависимость

public class SomeService {
    private readonly IEventBus eventBus;

    public SomeService(IEventBus eventBus) {
        this.eventBus = eventBus;
    }

    public SomeAction() {
        if (eventBus != null) {
            eventBus.publish("SomeAction Happened!");
        }

        //...
    }
}

, в противном случае рассмотримпередавая его явно методу как необязательная зависимость

public SomeAction(IEventBus eventBus = null) {
    if (eventBus != null) {
        eventBus.publish("SomeAction Happened!");
    }

    //...
}

Принцип явных зависимостей гласит:

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

выделение шахты

Внедрение IServiceProvider обсуждается как анти-шаблон, поскольку он следует шаблону локатора службы.

Существуют некоторые исключения, например, если зависимый класс используетсятакже используется в качестве фабрики.

...