Ответ 1
У меня был тот же вопрос, что и вы, когда я начал изучать Кинжал 2 пару недель назад. Я нашел информацию об этом (и большинстве других вопросов, связанных с кинжалом 2), которые трудно найти, поэтому я надеюсь, что это поможет!
Самый простой ответ - вы не можете. То, что вы ищете, это то, что называется вспомогательной инъекцией, и оно не является частью кинжала 2. Некоторые другие рамки инъекций зависимостей (DI), такие как Guice, предложите эту функцию, чтобы вы могли изучить их. Конечно, есть еще способы сделать то, что вы хотите сделать, используя Dagger 2.
Заводы фабрик фабрик
Стандартный способ делать то, что вы хотите сделать в сочетании с DI, - это использовать шаблон Factory. В принципе, вы создаете инъекционный класс Factory, который принимает параметры времени выполнения, такие как address
, в качестве аргументов для методов создания объектов, которые он предоставляет.
В вашем случае вам понадобится UtilFactory
, в который Dagger 2 вводит Validator
при создании и предлагает метод create(String address)
, который создает экземпляры Util
. UtilFactory
должен содержать ссылку на введенный экземпляр Validator
, чтобы он имел все необходимое для создания экземпляра Util
в методе create
.
Код для многих таких заводов может быть громоздким. Вы обязательно должны взглянуть на AutoFactory, что облегчает часть бремени. Похоже, что инъекция с помощью Guice работает очень похоже на Dagger 2 + AutoFactory (хотя и с более приятным синтаксическим сахаром).
Дополнительные модули/компоненты
Я сомневаюсь, что это то, что вы хотели бы сделать в этом случае, но вы могли бы просто создать модуль, который предоставляет адрес (и создать экземпляр нового компонента). Вам не нужно создавать новый класс @Module для каждого возможного адреса. Вместо этого вы можете просто передать адрес в качестве аргумента конструктору модуля. Вы можете использовать аннотацию @BindsInstance, предложенную teano для достижения аналогичного результата.
Я не уверен, что это анти-шаблон или нет. Для меня это похоже на приемлемый маршрут в некоторых случаях, но только тогда, когда вы фактически используете тот же, например. адрес для инициализации "многих" объектов. Вы определенно не хотите создавать экземпляр нового компонента и новую модель для каждого объекта, требующего инъекции. Это не эффективно, и если вы не будете осторожны, вы получите больше кода шаблона, чем без кинжала.
Не используйте (всегда) DI: Инъекции против нововведений
Что-то, что было очень полезно для меня при изучении каркасов DI, заключалось в том, что использование рамки DI не означает, что вы должны инициализировать все свои объекты DI. Как правило: вводите объекты, которые вы знаете во время компиляции, и которые имеют статические отношения с другими объектами; не вводите информацию о времени выполнения.
Я думаю, это - хорошая статья на эту тему. В нем представлена концепция "новизны" и "инъекции".
- Инъекции - это классы рядом с корнем вашего графика DI. Экземпляры этих классов - это те объекты, которые вы ожидаете, чтобы ваша инфраструктура DI обеспечивала и вводила. Объекты типа "менеджер" или "сервис-тип" являются типичными примерами инъекций.
- Newables - это объекты на границах вашего графика DI или вообще не являются частью вашего графика DI.
Integer
,address
и т.д. являются примерами новых возможностей.
В широком смысле, новизна - это пассивные объекты, и нет смысла вводить или издеваться над ними. Обычно они содержат "данные", которые находятся в вашем приложении, и доступны только во время выполнения (например, ваш адрес). Newables не должны содержать ссылки на инъекции или наоборот (то, что автор сообщения упоминает как "инъекционное/новое разделение" ).
В действительности я обнаружил, что не всегда легко или возможно провести четкое различие между инъекционными и новыми. Тем не менее, я думаю, что они - хорошие концепции, которые можно использовать как часть вашего процесса мышления. Определенно подумайте дважды, прежде чем добавить еще один Factory в свой проект!
В вашем случае, я думаю, было бы разумно рассматривать Util
как инъекционную, а адрес - как новый. Это означает, что адрес не должен быть частью класса Util
. Если вы хотите использовать экземпляр Util
, например. validating/... address, просто передайте адрес, который вы хотите проверить как аргумент метода validation/....