[C#] Как избежать безумства конструктора конструкции зависимостей?



Answers

Я не думаю, что у ваших конструкторов классов должна быть ссылка на ваш контейнерный период IOC. Это представляет собой ненужную зависимость между вашим классом и контейнером (тип зависимости, который МОК пытается избежать!).

Question

Я считаю, что мои конструкторы начинают выглядеть так:

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

с постоянно увеличивающимся списком параметров. Поскольку «Контейнер» является контейнером для инъекций, почему бы просто не сделать это:

public MyClass(Container con)

для каждого класса? Каковы недостатки? Если я это сделаю, мне кажется, что я использую прославленную статику. Пожалуйста, поделитесь своими мыслями о безумии безумства в IoC и Dependency Injection.




Я столкнулся с подобным вопросом о зависимостях Injection от конструктора и о том, насколько сложным он передавался во всех зависимостях.

Одним из подходов, который я использовал в прошлом, является использование шаблона фасада приложения с использованием уровня сервиса. У этого был бы грубый API. Если эта услуга зависит от репозиториев, она будет использовать инсталляцию setter для частных свойств. Для этого требуется создание абстрактной фабрики и перемещение логики создания хранилищ на фабрику.

Подробный код с пояснениями можно найти здесь

Рекомендации по IoC в сложном сервисном слое




Проблема:

1) Конструктор с постоянно увеличивающимся списком параметров.

2) Если класс наследуется (Ex: RepositoryBase ), то изменение сигнатуры конструктора вызывает изменение в производных классах.

Решение 1

Пропустить IoC Container для конструктора

Зачем

  • Не более возрастающий список параметров
  • Подпись конструктора становится простой

Почему нет

  • Делает вас классом, тесно связанным с контейнером IoC. (Это вызывает проблемы, когда 1. вы хотите использовать этот класс в других проектах, где вы используете другой контейнер IoC. 2. вы решили изменить контейнер IoC)
  • Делает вас класс менее наглядным. (Вы действительно не можете посмотреть на конструктор классов и сказать, что ему нужно для функционирования.)
  • Класс может получить доступ ко всему сервису.

Решение 2

Создайте класс, который группирует все службы и передает их конструктору

 public abstract class EFRepositoryBase 
 {
    public class Dependency
    {
        public DbContext DbContext { get; }
        public IAuditFactory AuditFactory { get; }

         public Dependency(
            DbContext dbContext,
            IAuditFactory auditFactory)
        {
            DbContext = dbContext;
            AuditFactory = auditFactory;
        }
    }

    protected readonly DbContext DbContext;        
    protected readonly IJobariaAuditFactory auditFactory;

    protected EFRepositoryBase(Dependency dependency)
    {
        DbContext = dependency.DbContext;
        auditFactory= dependency.JobariaAuditFactory;
    }
  }

Производный класс

  public class ApplicationEfRepository : EFRepositoryBase      
  {
     public new class Dependency : EFRepositoryBase.Dependency
     {
         public IConcreteDependency ConcreteDependency { get; }

         public Dependency(
            DbContext dbContext,
            IAuditFactory auditFactory,
            IConcreteDependency concreteDependency)
        {
            DbContext = dbContext;
            AuditFactory = auditFactory;
            ConcreteDependency = concreteDependency;
        }
     }

      IConcreteDependency _concreteDependency;

      public ApplicationEfRepository(
          Dependency dependency)
          : base(dependency)
      { 
        _concreteDependency = dependency.ConcreteDependency;
      }
   }

Зачем

  • Добавление новой зависимости к классу не влияет на производные классы
  • Класс является агностиком контейнера IoC
  • Класс описателен (в аспекте его зависимостей). По соглашению, если вы хотите знать, какой класс A A.Dependency , эта информация накапливается в A.Dependency
  • Подпись конструктора становится простой

Почему нет

  • необходимо создать дополнительный класс
  • регистрация сервиса становится сложной (вам необходимо регистрировать каждую X.Dependency отдельно)
  • Концептуально то же, что и IoC Container
  • ..

Решение 2 является просто необработанным, хотя, если есть твердый аргумент против него, тогда будет оценен описательный комментарий




Links