#dependency-injection #ioc-container #simple-injector
#внедрение зависимостей #ioc-контейнер #простой инжектор
Вопрос:
(РЕДАКТИРОВАТЬ: после написания этого вопроса я нашел по крайней мере одно решение, поэтому на этот вопрос есть ответ самостоятельно. Все равно может пригодиться пара глаз, которые знают о контейнерах IoC больше, чем я.)
У меня есть очень особый сценарий, который пахнет так, как будто он может использовать контейнер IoC, но техническая деталь затрудняет использование существующих.
Сценарий заключается в том, что я играю со следующим разделением компонентов пользовательского интерфейса (фактически компонентов Blazor, поэтому давайте назовем их Component
s) от классов моделей, с которыми они затем связываются (давайте назовем их UiObject
s).
Все UiObject
s имеют значение по умолчанию Component<U>
(т.е. where U : IUiObject
), который может привязываться к ним (think U
= IUiCommand
to GenericButtonComponent
быть a Component<IUiCommand>
и т. Д.), Но дизайнер пользовательского интерфейса может переопределить стиль и логику, добавив новый SpecialButtonComponent
, также являющийся a Component<UiCommand>
, с которым затем также можно использовать IUiCommand
. Этот специальный компонент может отличаться от старого в html, css и даже логике с отслеживанием состояния, но он всегда является заменой по умолчанию.
Я знаю, что нужен какой-то гибкий способ выбора правильного Component<U>
для каждого U
, который является a IUiObject
, на основе всевозможных вещей (сбор из asseblies, конфигурация xml, умные механизмы для приоритизации типов друг над другом и т. Д.).
Можно подумать, что это именно то, для чего созданы контейнеры IoC, но есть одна загвоздка: Blazor ожидает, что я буду доставлять типы, а не экземпляры, которые Blazor затем создает сам. Мне нужен
Type componentType = container.ResolveType<IUiCommand>()
Я поверхностно посмотрел на Autofac, Castle Windsor, Lamar, LightInject, SimpleInjector и только после написания этого вопроса понял, что по крайней мере SimpleInjector может разрешить a DependencyMetadata<IFoo>
, содержащий разрешенный тип — пока не повезло с какой-либо другой структурой.
Итак, я отвечу на свой собственный вопрос здесь, но мне все равно было бы любопытно, какие другие контейнеры IoC имеют эту функцию.
Комментарии:
1. В .NET 5 существует
IComponentActivator
абстракция. Это позволяет переопределять разрешение компонентов Blazor. Это позволяет вам создавать эти экземпляры самостоятельно или делегировать их контейнеру.
Ответ №1:
Простой инжектор может разрешить a DependencyMetadata<IFoo>
, содержащий разрешенный тип, например:
var implementationType =
container.GetInstance<DependencyMetadata<IFoo>>()?.ImplementationType;