(Автоматически) Механизмы привязки инъекций зависимости
Два общих механизма для создания привязок внедрения зависимостей, например, через контейнер IOC, взяты из конфигурации XML или блока императивного кода. В этих случаях пара ключ-значение является явной (т. Е. Ключ = запрошенный тип, значение = возвращаемый тип).
Тем не менее, существует третий "эвристический" подход, при котором контейнеру приложения /IOC присваиваются только ключи [IMyClass], а затем контейнер отражает набор зависимостей сборки приложения, чтобы найти все соответствующие классу конкретные имена [MyClass]. Иными словами, значения "возвращаемого типа" обнаруживаются, а не объявляются.
То, что я хотел бы знать, имеет два аспекта:
- Какие контейнеры IOC (или другие инструменты позднего связывания) допускают эвристический подход? У этого подхода есть более распространенное имя?
- Существуют ли другие методы связывания, кроме трех, перечисленных в списке, которые используются на практике?
4 ответа
Это называется конвенциональной конфигурацией или автоматической регистрацией и поддерживается следующими контейнерами.NET DI:
Наиболее распространенные механизмы конфигурации, используемые для DI-контейнеров:
- XML
- Код как конфигурация
- Конвенциональная конфигурация
Четвертый, но необычный подход заключается в использовании атрибутов. Среда Managed Extensibility Framework является наиболее ярким примером этого подхода, который более распространен в Java.
То, что вы называете "эвристическим" подходом, - это то, что я называю условностями. Большинство контейнеров IoC позволяют вам переопределить способ разрешения привязок, что означает, что вы можете ввести любое соглашение, которое вы хотите. Нет таких соглашений по умолчанию, о которых я знаю. Скорее, большинство контейнеров ничего не делают по умолчанию; ваша задача - рассказать им, как разрешать типы, либо через файл конфигурации, либо через код.
Пример пользовательского соглашения, которое я нахожу, довольно распространено, что экономит много объявлений: если запрошенный тип является типом интерфейса, начинающимся с "I" и заканчивающимся "Service", тогда попытайтесь создать и разрешить тип с тем же именем кроме "я". Это разрешит имена как IFooService
в FooService
автомагически. Кроме того, вы можете легко внедрить логику для выбора разных сервисов в разных контекстах, а также управлять временем жизни экземпляров сервиса в общем месте.
Поскольку вы можете переопределить привязку большинства контейнеров IoC, вы также можете ввести и другие варианты поведения. Как правило, однако, на самом деле есть два варианта:
- Конфигурировать во время выполнения (через файлы конфигурации, такие как файлы XML)
- Настраивать во время компиляции (либо через декларативный DSL-подобный API, либо через пользовательские соглашения или другую форму пользовательской логики)
Я обычно делал то, что вы описываете как пользовательский шаг в конфигурации. AFAIK - нет контейнера, обеспечивающего готовую такую стратегию (и, на мой взгляд, это не часть контейнера, а конфигурируемый материал, который должен быть внешним от ответственности контейнера).
Поскольку я довольно часто использовал StructureMap, я знаю, как сделать такую вещь с этим контейнером: в основном это будет соглашение о пользовательской регистрации (из инициализации или реестра перейдите в блок Scan-lambda и найдите "соглашение"). "метод".
Это позволяет вам просматривать отраженные типы, а затем вставлять их в конфигурацию контейнера по своему усмотрению. Это должно позволить то, что вы пытаетесь сделать.