Введите массив интерфейсов в Ninject

Рассмотрите следующий код.

public interface IFoo { }


public class Bar
{
    public Bar(IFoo[] foos) { }
}


public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<IFoo[]>().ToConstant(new IFoo[0]);
        // ToConstant() is just an example
    }
}


public class Program
{
    private static void Main(string[] args)
    {
        var kernel = new StandardKernel(new MyModule());
        var bar = kernel.Get<Bar>();
    }
}

Когда я пытаюсь запустить программу, я получаю следующее исключение.

Ошибка, активирующая IFoo
Никакая привязка соответствия не доступна, и тип не самосвязываем.
Путь активации:
2) Инжекция зависимости IFoo в параметр foos конструктора печатающей штанги
1) Запрос на панель

Как я могу ввести / связывают с массивом в Ninject?

Спасибо за внимание.

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

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

    private IEnumerable<TInterface> GetInterfaceImplementations<TInterface>(IContext context)
    {
        return GetType().Assembly.GetTypes()
            .Where(t => typeof (TInterface).IsAssignableFrom(t) && IsConcreteClass(t))
            .Select(t => Kernel.Get(t)).Cast<TInterface>();
    }

Я чувствую себя немного виновным с точки зрения обхода контейнеров механизм DI. Действительно ли это - плохая практика? Существует ли обычная практика, чтобы сделать такие вещи?

Разрешение:
Я использую класс обертки в качестве bsnote предложенный.

14
задан Julian Lettner 24 June 2010 в 14:54
поделиться

2 ответа

Это в значительной степени повторение ответа @ bsnote (который я добавил + 1d), который может помочь понять, почему он работает таким образом.

Ninject (и другие структуры DI / addin) имеют две различные возможности:

  1. понятие привязки к одной однозначной реализации службы ( Get )
  2. Средство, которое позволяет одному чтобы получить набор служб [который затем программно выбирает один из или каким-то образом объединяет] ( GetAll / ResolveAll в Ninject)

В вашем примере кода используется синтаксис это связано с 2. выше. (например, в MEF обычно используются аннотации [ImportMany] , чтобы прояснить это)

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

Однако, как говорит @bsnote, один из способов рефакторинга вашего требования - обернуть массив либо в контейнер, либо иметь объект, который вы запрашиваете (например, фабричный метод или конструкцию типа репозитория)

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

РЕДАКТИРОВАТЬ: Есть набор примеров сканирования в расширениях, которые, как я полагаю, могут атаковать многие вещи, которые вы пытаемся сделать (в таких вещах, как StructureMap, такого рода вещи более интегрированы, что, очевидно, имеет свои плюсы и минусы).

В зависимости от того, пытаетесь ли вы достичь соглашения по конфигурации или нет, вы можете подумать о том, чтобы прикрепить интерфейс маркера к каждому типу плагина. Затем вы можете явно привязать каждого из них.В качестве альтернативы для CoC вы можете сделать цикл подпрограммы Load () модуля Module над набором генерируемых реализаций (т. Е. Множеством отдельных Get s ) в вашем редактировании.

В любом случае, когда у вас есть несколько регистраций, вы можете «запросить» T [] или IEnumerable и получить полный набор. Если вы хотите достичь этого явно (например, Service Locator и все, что он подразумевает - как и в вашем случае, вы можете использовать GetAll для их пакетной обработки, чтобы вы не выполняли цикл, который неявно вы сделали это.

Не уверен, установили ли вы эту связь или я что-то упускаю. В любом случае, я надеюсь, он научил вас вставлять код в вопросы, поскольку он говорит> 1000 слов: P

7
ответ дан 1 December 2019 в 13:08
поделиться

Для меня это тоже было проблемой. Ninject вводит каждый элемент массива вместо самого массива, поэтому у вас должно быть определено отображение для типа элементов массива. На самом деле нет возможности сопоставить массив как тип с текущей версией Ninject. Решение - создать оболочку вокруг массива. Например, можно использовать ленивый класс, если он вам подходит. Или вы можете создать свою собственную оболочку.

4
ответ дан 1 December 2019 в 13:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: