Контейнер IoC, который может разрешать типы, а не просто экземпляры

#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;