2012-01-13 2 views
18

Я пытался использовать Ninject сегодня и задать пару вопросов. Прежде всего, мне нужно использовать атрибут Inject для всех конструкторов, для которых я хочу использовать инъекцию. Это похоже на действительно хромой дизайн? Нужно ли мне создавать ядро, а затем использовать это везде, где я проходил в классе?Как использовать Ninject

ответ

22

First of all do I need to use the Inject attribute on all constructors that I want to use injection for. This seems like a really lame design?

Нет, вам не обязательно делать это вообще. Поскольку вы работаете с ASP.NET MVC, вы можете просто установить пакет Ninject.MVC3 Nuget. Это позволит вам начать с класса NinjectMVC3 в папке App_Start. Вы можете использовать метод RegisterServices для регистрации ваших интерфейсов/классов с помощью Ninject. Все контроллеры, которые имеют зависимости от этих интерфейсов, затем будут автоматически разрешены Ninject, нет необходимости в атрибуте Inject. не

Do I need to create a Kernel then use that everywhere I pass in an injected class?

Нет - то, что вы описываете звуки больше похожи на Service Locator pattern, не зависимо инъекции - вы хотите передать в своих зависимостей в идеале в конструкторе, вместо того, чтобы решить их в рамках конкретных классов, использующих ядро. Должен быть только один центральный корневой состав, в котором выполняется разрешение, которое находится внутри корня композиции либо в методе RegisterServices, упомянутом выше, либо в отдельном модуле Ninject, созданном там - более поздний подход позволит вам немного больше гибкости и модульности (без каламбур предназначенный) при изменении способа разрешения зависимостей.

Вот хороший beginner's tutorial on dependency injection with Ninject and MVC3.

+0

Благодарим за предоставленную информацию. Теперь я удалил атрибут [Inject]. Я смотрел учебное видео, и именно там я научился это делать. Теперь мне нужно передать параметры доступа в разрешенный класс concreate, для которого я использую WithConstructorArgument, но я все еще получаю эту ошибку: для этого объекта не задан конструктор без параметров. –

+0

Плюс, я в замешательстве, ссылка, которую вы разместили, также использует подход StandardKerbal. Мое понимание DI заключалось в том, что контейнер автоматически разрешал зависимости (в зависимости от настроек, которые вы установили). –

+0

@Sachi: вам не нужно 'WithConstructorArgument()' либо, если параметры, которые необходимо передать, также разрешены с помощью Ninject - подумайте об этом как о графике – BrokenGlass

58

Лучший способ начать работу с Ninject - начать с малого. Найдите new.

Где-то в середине вашего приложения вы создаете класс внутри другого класса. Это означает, что вы создаете зависимость . Инъекция зависимостей составляет около , проходящих в этих зависимостях, обычно через конструктор, вместо вложения их.

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

class NoteCreator 
{ 
    public NoteHost Create() 
    { 
     var docCreator = new WordDocumentCreator(); 
     docCreator.CreateNewDocument(); 
     [etc.] 

WordDocumentCreator это класс, который обрабатывает специфику создания нового документа в Microsoft Word (создать экземпляр Word, и т.д.). Мой класс, NoteCreator, зависит от от WordDocumentCreator для выполнения его работы.

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

Теперь представьте себе, что я могу изменить свой класс, чтобы выглядеть следующим образом:

class NoteCreator 
{ 
    WordDocumentCreator docCreator; 

    public NoteCreator(WordDocumentCreator docCreator) // constructor injection 
    { 
     this.docCreator = docCreator; 
    } 

    public NoteHost Create() 
    { 
     docCreator.CreateNewDocument(); 
     [etc.] 

Мой код не сильно изменилось; все, что я сделал в методе Create, удаляет строку с new. Но теперь я ввожу свою зависимость.Давайте сделаем еще одно небольшое изменение:

class NoteCreator 
{ 
    IDocumentCreator docCreator; 

    public NoteCreator(IDocumentCreator docCreator) // change to interface 
    { 
     this.docCreator = docCreator; 
    } 

    public NoteHost Create() 
    { 
     docCreator.CreateNewDocument(); 
     [etc.] 

Вместо передачи в бетонWordDocumentCreator, я извлек интерфейсIDocumentCreatorс методом CreateNewDocument. Теперь я могу передать любой класс, который реализует этот интерфейс, и все, что нужно сделать, это вызвать метод, о котором он знает.

Теперь сложная часть. Теперь у меня должна быть ошибка компиляции в моем приложении, потому что где-то я создавал NoteCreator с конструктором без параметров, который больше не существует. Теперь мне нужно вытащить , что и зависимость. Другими словами, я просматриваю тот же процесс, что и выше, но теперь я применяю его к классу, который создает новый NoteCreator. Когда вы начнете извлекать зависимости, вы обнаружите, что они склонны «всплывать» в корень вашего приложения, а именно место, где вы должны иметь ссылку на ваш контейнер DI (например, Ninject).

Другое, что мне нужно сделать, это configure Ninject. Существенная часть представляет собой класс, который выглядит следующим образом:

class MyAppModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IDocumentCreator>() 
      .To<WordDocumentCreator>(); 

Это говорит Ninject, что, когда я пытаюсь создать класс, который, где-то вниз по линии, требующую IDocumentCreator, он должен создать WordDocumentCreator и использовать. Процесс Ninject проходит через что-то вроде этого:

  • Создать приложение MainWindow. Для его конструктора требуется NoteCreator.
  • ОК, поэтому создайте NoteCreator. Но его требуется конструктор IDocumentCreator.
  • В моей конфигурации указано, что для IDocumentCreator я должен использовать WordDocumentCreator. Так создайте WordDocumentCreator.
  • Теперь я могу передать WordDocumentCreator NoteCreator.
  • И теперь я могу передать это NoteCreator на MainWindow.

Красота этой системы в три раза.

Во-первых, если вы ничего не сконфигурируете, вы сразу узнаете, потому что ваши объекты создаются сразу после запуска вашего приложения. Ninject предоставит вам полезное сообщение об ошибке, в котором говорится, что ваш IDocumentCreator (например) не может быть разрешен.

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

  • Написать WordPerfectDocumentCreator, который реализует IDocumentCreator.
  • Изменить MyAppModule выше, переплет IDocumentCreator до WordPerfectDocumentCreator вместо.

В-третьих, если я хочу, чтобы проверить мой NoteCreator, я не должен проходить в реальномWordDocumentCreator (или все, что я использую). Я могу передать подделку. Таким образом, я могу написать тест, который принимает. Мой IDocumentCreator работает правильно и проверяет только движущиеся части в NoteCreator. Мой подделка IDocumentCreator ничего не даст, но вернет правильный ответ, и мой тест будет следить за тем, чтобы NoteCreator поступал правильно.

Для получения дополнительной информации о том, как структурировать свои приложения таким образом, взгляните на недавнюю книгу Марка Семанна, Dependency Injection in .NET. К сожалению, он не охватывает Ninject, но он охватывает целый ряд других фреймворков DI, и он рассказывает о том, как структурировать ваше приложение так, как я описал выше.

Также посмотрите на Working Effectively With Legacy Code, by Michael Feathers. Он говорит об испытательной стороне выше: как разрывать интерфейсы и пропускать подделки с целью изолировать поведение и подвергать его тестированию.

+4

Действительно приятное объяснение как для Injection Dependency, так и для Ninject! Спасибо, и я копирую его в свою Evernote для дальнейших ссылок. – Tarik

+0

@Kyralessa Это действительно отличное объяснение. Одно из лучших, что я прочитал до сих пор, ясное и замкнутое. То, что вы делаете в начале, называется инъекцией Dependecy для бедных людей? –

+0

Ничего себе лучшее объяснение, которое я видел до сих пор, дает этому человеку картошку. +1 –

7

Не забудьте, что есть документы, в том числе введение, которое я считаю очень подходящим, учитывая вопросы, которые вы задаете on the Ninject Wiki. Вы просто раздражаете себя, если пытаетесь использовать Ninject, не читая его до конца.

Прикрепите table of contents на панели закладок.

Я также могу порекомендовать Mark SeemannDependency Injection in .Net в качестве компаньона для архитектуры, основанной на DI (хотя это не касается непосредственно Ninject).

Смежные вопросы