Создание ядра без библиотеки внутри библиотеки классов - PullRequest
8 голосов
/ 11 февраля 2010

У меня есть класс с зависимостями, которые я связал с Ninject.

public interface IFoo {}

public class MyObject {
    [Inject]
    IFoo myfoo;
}

В реальной реализации я использую инъекцию свойств, но для быстрой иллюстрации я добавлю в поле. Как я понимаю, вместо новых экземпляров MyObject, для правильного внедрения зависимостей мне нужно использовать

kernel.Get<MyObject>()

Однако я спотыкаюсь о том, что MyObject будет использоваться только в контексте библиотеки классов. Цель состоит в том, чтобы конечные приложения создавали свои собственные модули и передавали их в экземпляр ядра для гидратации. Учитывая это, каков вообще самый прагматичный способ приблизить появление общего экземпляра ядра Ninject к моей библиотеке классов, чтобы экземпляры MyObject (и других подобных случаев) могли быть гидратированы?

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

Так в RandomService.cs

var myKernel = NinjaFactory.Unleash();
var myobj = myKernel.Get<MyObject>();
myobj.foo();

Прежде чем я зайду слишком далеко по этому пути, мне нужно проверить здравомыслие, чтобы убедиться в правильности мышления или в том, что нет чего-то другого, чего я упускаю. Я, очевидно, новичок в IoC и чувствую, что начинаю понимать основы, но не обязательно лучшие способы использования в реальных условиях.

Ответы [ 3 ]

9 голосов
/ 11 февраля 2010

Я не уверен, что понимаю все детали вашего вопроса, но я, насколько я понимаю, вы спрашиваете, как вы можете вывести зависимость от Ninject.

Можно написать DI-дружественные библиотеки, даже не ссылаясь на какой-либо конкретный DI-контейнер (Ninject или что-либо еще). Это оставляет потребителя библиотеки открытым для выбора контейнера DI по своему вкусу (или вообще не использует контейнер). Этот подход очень предпочтителен, потому что он обеспечивает большую степень свободы.

Тем не менее, вы должны отдать предпочтение Внедрение конструктора более Внедрение свойства . Хотя внедрение свойства кажется обманчиво простым в реализации, на самом деле это довольно сложно сделать правильно.

Одним из больших преимуществ внедрения конструктора является то, что вам не нужно помещать какие-либо атрибуты в конструктор, потому что он структурно уже несет всю информацию, необходимую для контейнера DI, чтобы правильно подключить его.

4 голосов
/ 11 февраля 2010

Точка Марка определенно является моей отправной точкой (следовательно, +1) по этому вопросу. NB Не забудьте перейти по его ссылке .

Я, например, был виновен в том, что слишком рано отказался от конструктора над свойствами (или полями) (мое «оправдание» заключалось в том, что, поскольку базовому классу требовалось 5 свойств, я не хотел обременять этим все производные классы. Решение этой проблемы состояло в том, чтобы обернуть 5 свойств, включенных в класс или иерархию классов, представляющих любые базовые понятия, которые представляют свойства. Немного похоже на рефакторинг Int вводить объект параметра.

Хорошее обсуждение соображений, которые я считаю полезными: http://thinkbeforecoding.com/post/2009/05/15/IOC-container-go-hide (не могу найти SO сообщение, в котором упоминается его и некоторые темы вокруг него, возможно, кто-то вставит ссылку: D)

Еще один блог, в котором обобщаются некоторые из этих пунктов, - Ваш контейнер IoC показывает

А http://davybrion.com/blog/2009/11/integrating-your-ioc-container-with-agatha/

0 голосов
/ 24 августа 2012

Вот хороший универсальный рецепт для поиска всех модулей в текущей сборке:

IKernel _serviceKernel = new StandardKernel();

Assembly myAssembly = this.GetType().Assembly;

IEnumerable<Type> ninjectModuleTypes = 
     myAssembly.GetTypes().Where(type => type.BaseType == typeof(NinjectModule));

foreach (Type ninjectModuleType in ninjectModuleTypes)
{
    NinjectModule mod = (NinjectModule)Activator.CreateInstance(ninjectModuleType);
    _serviceKernel.Load(mod);
}
...