Ninject: Как мне внедрить в библиотеку классов? - PullRequest
6 голосов
/ 30 октября 2009

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

    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 <> () - Однако ... Поскольку приведенный выше код находится в библиотеке классов, я не у меня нет доступа к ядру. Как я могу получить ядро ​​с этого момента или есть лучший способ сделать это?

Ответы [ 2 ]

8 голосов
/ 31 октября 2009

Хороший вопрос, чтобы спросить.

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

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

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

Еще одна вещь, на которую стоит обратить внимание, - это Common Service Locator, который позволит сделать библиотеку нейтральной к контейнеру, хотя за пределами EL вы не найдете много использования, так как вы не должны действительно показывать свой контейнер .

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

РЕДАКТИРОВАТЬ: В Ninject 2 нет необходимости явно передавать Kernel экземпляров, как я уже сказал - можно просто запросить IKernel в вашем ctor, и вы получите его, независимо от разрешения запрос явно передает один дюйм.

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

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

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

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;
 }
}
...