2009-10-30 2 views
6

Для начала я использую Ninject 1.5. У меня есть два проекта: веб-проект и библиотека классов. Моя конфигурация DI находится в веб-проекте. В моей библиотеке классов У меня есть следующие определены:Ninject: Как я вставляю в библиотеку классов?

public interface ICacheService<T> 
    { 
      string Identifier { get; } 
      T Get(); 
      void Set(T objectToCache, TimeSpan timeSpan); 
      bool Exists(); 
    } 

А затем конкретный класс называется CategoryCacheService.

В моем веб-проекта я связываю два:

Bind(typeof(ICacheService<List<Category>>)).To(typeof(CategoryCacheService)).Using<SingletonBehavior>(); 

В моей библиотеке классов У меня есть методы расширения для класса HtmlHelper, например:

public static class Category 
{ 
    [Inject] 
    public static ICacheService<List<Category>> Categories { get; set; } 

    public static string RenderCategories(this HtmlHelper htmlHelper) 
    { 
    var c = Categories.Get(); 

    return string.Join(", ", c.Select(s => s.Name).ToArray()); 
    } 
} 

Мне сказали, что вы не может вводить в статические свойства, вместо этого я должен использовать Kernel.Get <>() - Однако ... Поскольку код выше находится в библиотеке классов, у меня нет доступа к ядру. Как я могу получить Ядро с этого момента или есть лучший способ сделать это?

ответ

8

Хороший вопрос.

Половина идеи использования DI заключается в том, чтобы удалить беспокойство/тонкую настройку поведения инстинктов из кода под инъекцией. Следовательно, имеет смысл изменить класс Category, чтобы он больше не был static, объявите его зависимости в ctor и пусть код клиента сшит его вместе.

Относительно доступа к нему, если вы действительно уверены, что это хорошая идея ... Как правило, идея в вашем случае заключалась бы в создании CacheServiceResolver и регистрации его [в вашем веб-проекте]. Затем передайте ему экземпляр Kernel. Таким образом, ваша DLL связана только с интерфейсом вашего CacheServiceResolver.

Другой подход, который часто используется, заключается в том, что объект «Service Locator» последнего объекта где-то глобальный, который предоставляет «GlobalGet». Но это, как правило, «плохая идея», и ее следует использовать только для временных каналов Taping.

Другая вещь, на которую стоит обратить внимание, это общий сервис-локатор, который позволит создать нейтральную библиотеку, хотя и вне EL, вы не найдете много использования в качестве you shouldnt really show your container.

Другой вариант - потребовать 0 фабричный метод Func<T> и Bind, что на лямбда, которая его решает, извлекая этот поиск из вашего кода.

EDIT: В Ninject 2, нет необходимости явно передавать в Kernel случаях, как я уже говорил - можно просто попросить IKernel в вашем CTOR, и вы получите его, независимо от того, expclicitly передает запрос на разрешение один в.

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

  1. нет контейнеров артефакты, оставить сшивание для клиента
  2. обеспечить контейнер нейтральной точки расширения, с учетом конкретно чего-то достичь в контексте вашей библиотеки, используя терминология в повсеместном языке домена вашей библиотеки вместо нейтрализованных абстрактных терминов контейнера
  3. обеспечивает контейнер нейтрального подход к интеграции а-ля Common Service Locator
  4. только тогда рассмотреть возможность людей, нуждающиеся в
    • знать ваш контейнер
    • понять ваш контейнер
+0

Ruben, CacheServiceResolver кажется правильной идеей для меня, поскольку Я могу повторно использовать этот шаблон в будущем. Есть ли у вас примеры настройки преобразователя? – DennyFerra

+0

К сожалению, у меня нет руки. Общая идея заключалась бы в том, что везде, где вы создаете свой новый стандартный класс, вы указываете ссылку на него. Тогда у вас есть что-то такое же простое, как 'void RegisterCacheServiceResolver (ядро ядра) {Bind (). ToConstant (новый CacheServiceResolver (ядро));}' на одном из модулей, которому вы передаете ядро. Или вы можете создать Ядро, а затем передать его конструктору любого модуля, который ему нужен, после чего вы добавите модуль [в отличие от передачи их всех в конструктор ядра как обычно). –

4

В веб-проекта выполните следующую команду из пакета Manager.

Install-Package Ninject.MVC3 

Вы должны получить модуль NinjectWebCommon в папке App_Start.

К нижней части вы можете добавить свою зависимость, как показано ниже:

private static void RegisterServices(IKernel kernel) 
{ 
kernel.Bind<IPeopleRepository>().To<PeopleRepository>(); 
} 

из вашей библиотеки проекта класса выполните следующую команду:

Install-Package Ninject 

Это, как внедрить услугу с хранилищем от библиотека классов:

public class PeopleService : IPeopleService 
{ 
private readonly IPeopleRepository _peopleRepository; 

[Inject] 
public PeopleService(IPeopleRepository peopleRepository) 
{ 
    this._peopleRepository = peopleRepository; 
} 
} 
Смежные вопросы