Ninject 2.0-привязка к объекту, использующему один и тот же интерфейс более одного раза?
Рассмотрим следующее:
public Something(IInterface concreteObjectOne, IInterface concreteObjectTwo)
{
this.concreteObjectOne = concreteObjectOne;
this.concreteObjectTwo = concreteObjectTwo;
}
Как установить этот тип привязки с помощью Ninject? Я бы попробовал погуглить термин, но так как я не уверен, как это называется, Я не могу, и я не могу найти ничего на Вики об этом.
Edit:
Я полагаю, что это называется связыванием на основе Конвенции, как описано здесь . Однако эта документация для версий 1.0 и 2.0 не имеет метода
Only. Я бы хотел, чтобы это было достигнуто без атрибутов-с помощью условность имен или что-то подобное. 2 ответов:
В дополнение к использованию метода" только", в статье предлагается другое решение путем указания различных атрибутов для вводимых объектов.
Пример:
public class ObjectOneAttribute : Attribute { } public class ObjectTwoAttribute : Attribute { }Затем
public Something([ObjectOneAttribute] IInterface concreteObjectOne, [ObjectTwoAttribute] IInterface concreteObjectTwo) { this.concreteObjectOne = concreteObjectOne; this.concreteObjectTwo = concreteObjectTwo; }И когда вы хотите привязать интерфейс к правильному конкретному объекту, используйте метод "WhereTargetHas":
Bind<IInterface>().To<YourConcreteTypeOne>().WhereTargetHas<ObjectOneAttribute>(); Bind<IInterface>().To<YourConcreteTypeTwo>().WhereTargetHas<ObjectTwoAttribute>();Обновление: решение без использования атрибутов:
Используйте метод "Когда":Bind<IInterface>().To<YourConcreteTypeOne>().When(r => r.Target.Name == "concreteObjectOne"); Bind<IInterface>().To<YourConcreteTypeTwo>().When(r => r.Target.Name == "concreteObjectTwo");
Если мне будет позволено предложить некоторые общие, а не конкретные указания по этому вопросу, я бы предложил вам немного пересмотреть свой проект. Текущий конструктор является расплывчатым , потому что он не дает никаких указаний о том, какая реализация IInterface идет куда - я понимаю, что это просто макет вашего реального API, и хотя реальный API может предложить больше помощи человеческому разработчику в виде метко названных параметров, машина, подобная контейнеру DI, не может сделать правильный вывод. использование.
Многие контейнеры DI предлагают некоторый способ устранения такой неопределенности, например, предоставляя атрибуты, которые можно использовать для связывания имен (метаданных) с каждой зависимостью. AFAIR, Ninject имеет атрибуты
Inject...Однако рассмотрим несколько альтернатив:
Первый вариант-инкапсулировать два похожих экземпляра интерфейса в объект параметра , например:public interface IParameterObject { IInterface ObjectOne { get; } IInterface ObjectTwo { get; } }Теперь вы можете изменить конструктор, чтобы взять экземпляр IParameterObject вместо самих двух экземпляров интерфейса.
public Something(IParameterObject po) { this.concreteObjectOne = po.ObjectOne; this.concreteObjectTwo = po.ObjectTwo; }Это означает, что вы можете переместить конфигурацию IParameterObject в корень композиции .
Другой альтернативой размышлению является то, имеет ли смысл рассматривать случай с двумя экземплярами как просточастный случай более общей конструкции, которая принимаетлюбое число экземпляров. Это может быть не всегда так, но если это так, вы можете изменить конструктор следующим образом:public Something(IEnumerable<IInterface> objects)Я бы так и сделал. лично я предпочитаю любое из вышеперечисленных предложений всему, что использует конкретные функции Ninject, потому что это заставляет меня сделать API более явным в целом, и, следовательно, более читаемым и доступным для обслуживания.
Comments