#.net #dependency-injection #inversion-of-control
#.net #внедрение зависимости #инверсия контроля
Вопрос:
Меня раздражает необходимость передавать объекты сантехники через конструктор, потому что я хотел бы зарезервировать аргументы конструктора для бизнес-объектов или значений для передачи.
Итак, я хотел бы пройти мимо установщиков, но мой объект, который содержит зависимости, не должен создаваться до тех пор, пока эти установщики не будут заполнены.
Как это сделать без связки if dependency01 not empty и dependency02 not empty, зная, что ОБА не должны быть пустыми?
Ответ №1:
Вы не можете ничего установить для объекта, пока не будет создан его экземпляр, поэтому ваше требование (как указано) невозможно.
Если бы вы использовали статический фабричный метод, вы могли бы использовать установщики — но для этого потребовалось бы, чтобы ваш конструктор был закрытым, так что на самом деле ничего не меняется за пределами конструктора.
Вы могли бы использовать Initialize
метод, который зависит от установки определенных свойств, но тогда вам придется полагаться на вызов этого метода. Это означает либо много работы, чтобы убедиться, что метод был вызван (например, должен вызываться каждый метод класса if (!IsInitialized) throw ...
), либо вы просто привносите хрупкость в свой код.
Любое альтернативное решение менее надежное или требует больше работы, чем просто помещение абсолютно необходимых данных в ваш конструктор — для чего и нужен параметр конструктора. Мое предложение состояло бы в том, что вам нужно пересмотреть ваше произвольное требование о том, чтобы параметры конструктора были «зарезервированы» в пользу чего-то, что имеет больше технического смысла.
Комментарии:
1. Это не произвольно: я хочу использовать конструктор бизнес-объектов для бизнес-зависимостей и не смешивать объекты инфраструктуры с бизнес-материалами. Это вопрос разделения проблем как таковых.
2. Да, но ваше «разделение задач» не относится к тому месту, куда вы пытаетесь это поместить. Конструктор против свойств — это не то место, где вы применяете разделение задач — я подозреваю, что у вас слишком мало классов!
Ответ №2:
Вы могли бы создать фабричный класс, который принимает зависимости.
factory = new Factory(dep01, dep02);
И используйте метод create для передачи вашего бизнес-объекта.
factory.Create(someBusinessObject);
Мне не совсем нравится это (неправильное) использование конструктора factory, но это решает вашу проблему.
Ответ №3:
Вы пытаетесь обойти конструктор. Если объектам действительно требуется, чтобы объект находился в согласованном состоянии, я бы предложил повторно рассмотреть возможность использования constructor для этой цели.
РЕДАКТИРОВАТЬ: С моей точки зрения, лучшим является шаблон builder, который сочетает в себе лучшее из обоих:
- Разрешить создание неизменяемых объектов (!) — установщики нарушают это
- Позволяет устанавливать зависимости по имени вместо использования индексов — самое большое (если не единственное) преимущество установщиков
Комментарии:
1. Я не пытаюсь обойти конструктор, я хочу использовать конструктор бизнес-объектов для бизнес-зависимостей и не смешивать объекты инфраструктуры с бизнес-материалами.
2. Неважно. Я просто не понимаю, почему людям не нравится использовать конструкторы. Посмотрите этот хороший пост на эту тему, если вы серьезно заинтересованы в этой теме: googletesting.blogspot.com/2009/02 /…
3. Я потратил на эту тему несколько вечеров, и вывод для меня — использовать шаблон builder. Который сочетает в себе (с моей точки зрения) лучшее из обоих подходов: разрешить создавать неизменяемый объект разрешить устанавливать зависимости по имени.