Передача параметров конструктора при разрешении типов в Unity: лучшая практика - PullRequest
3 голосов
/ 28 января 2010

Иногда необходимо использовать внедрение зависимостей, чтобы предоставить параметры для использования в конструкторе. Это то, что поддерживается в Unity (и других контейнерах внедрения зависимостей), поэтому, когда он пытается создать экземпляр типа, он может предоставить ваши аргументы в качестве параметров в конструкторе.

Мой вопрос: такой подход желателен?

В интерфейсе невозможно указать, какие параметры должен иметь класс реализации. Указывая параметры для Unity, вы предполагаете, что реализующий класс имеет эти параметры, и вы накладываете неявные ограничения на будущие реализующие классы. Эти ограничения не могут быть переданы через интерфейс.

Итак, это недостаток в том, как указываются сами интерфейсы (в .NET), например. Должна ли быть возможность указать подписи конструктора? Или эта функция (возможность предоставления параметров конструктора) была включена в Unity из-за какой-то другой необходимости?

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

Я ценю, что мой вопрос здесь может быть неясным, поэтому я задам его немного по-другому: каков наилучший способ внедрения зависимостей в классе, в котором есть конструктор, требующий параметров?

(Я не считаю этот вопрос субъективным, так как для этого типа внедрения зависимостей, вероятно, должен быть единый шаблон проектирования.)

EDIT:

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

Ответы [ 3 ]

2 голосов
/ 28 января 2010

Я не уверен, откуда у вас мысль, что инъекция в конструктор не соответствует DI. Я бы сказал, что реальная ситуация противоположна этому: внедрение конструктора - это один из самых распространенных шаблонов, используемых для достижения внедрения зависимостей - я бы сказал, что это самый распространенный шаблон и это представление, безусловно, подтверждается тем фактом, что большинство контейнеров Inversion of Control (DI-контейнеры) используют инъекцию конструктора в качестве предпочтительного механизма.

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

То, что вы говорите, используя шаблон внедрения конструктора, это то, что «я удаляю жестко закодированные зависимости внутри моего класса, определяя их как параметры, передаваемые в конструктор - мой класс не может быть создан без этих зависимостей». Конечно, первая половина этого утверждения является сущностью DI, но вторая половина усиливает это.

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

А что касается вашего утверждения о фабриках - это именно то, что представляют собой контейнеры IOC - большие фабрики, которые заботятся о дереве зависимостей решения, так что вам не нужно заботиться.

Редактировать

Я думаю, что, возможно, вы спрашиваете о случае, когда вы хотите предоставить параметр конструктора вне зависимости, такой как идентификатор для ссылочной сущности или enum начального состояния?

Лично я не вижу проблемы с контейнером IOC, позволяющей это сделать. Это все еще начальное состояние вашего класса, и, следовательно, правила для создания этого состояния должны быть явно выражены. Это может означать, что вам иногда нужно больше ссылок на ваш контейнер IOC, которые вам могут понравиться, но это не настолько ужасная ситуация, чтобы отказаться от других преимуществ инъекции в конструктор.

0 голосов
/ 27 октября 2014

Проблема здесь в том, что определение InjectionConstructor в Unity по сравнению с определением в Castle.Windsor.

В Unity, если вам нужно ввести определенный параметр, скажем, в AppSetting, вы также обязаны предоставить все остальные параметры, тем самым фиксируя сигнатуру конструктора. Однако в Castle.Windsor он принимает указанный вами параметр, а затем использует механизм разрешения, чтобы найти другие параметры обычным способом.

Можно было бы представить это в Unity, написав собственную стратегию Builder, в которой подход «наилучшего соответствия» подходил для конструктора, а не для жадности по умолчанию / предоставления всего, что по умолчанию.

0 голосов
/ 28 января 2010

Ответственность контейнеров IoC (скажем, Unity) заключается в подключении интерфейсов к конкретным реализациям. Это означает, что ваш контейнер должен знать интерфейс и как создавать объект, который реализует интерфейс. Использование конструктора для инъекций является абсолютно законным и рекомендуемым способом. Unity создаст конкретную реализацию, когда ваше приложение запрашивает интерфейс через метод Resolve (). Сам контейнер Unity - это фабрика, которая создает ваши объекты, вы используете Unity, потому что не хотите реализовывать эти фабрики самостоятельно.

...