Подтвердить что ты не робот

Как использовать Ninject

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

4b9b3361

Ответ 1

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

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

Нужно ли мне создавать Ядро, а затем использовать это везде, где я введенный класс?

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

Здесь хороший учебник для начинающих по инъекции зависимостей с Ninject и MVC3.

Ответ 2

Лучший способ начать работу с 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 с безпараллельным конструктором, который больше не существует. Теперь мне нужно также вытащить эту зависимость. Другими словами, я просматриваю тот же процесс, что и выше, но теперь я применяю его к классу, который создает новый NoteCreator. Когда вы начнете извлекать зависимости, вы обнаружите, что они имеют тенденцию "пузыриться" к корню вашего приложения, и это единственное место, где вы должны иметь ссылку на ваш контейнер DI (например, Ninject).

Другое, что мне нужно сделать, это настроить 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 делает правильные вещи.

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

Также смотрите Эффективно работая с устаревшим кодом, Майкл Перс. Он говорит об испытательной стороне вышеперечисленного: как разрывать интерфейсы и пропускать подделки с целью изолировать поведение и тестировать его.

Ответ 3

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

Немного поместите оглавление на панели закладок.

Я также могу рекомендовать Mark Seemann Инъекция зависимостей в .Net в качестве сопутствующей книги для архитектуры на основе DI (хотя она не распространяется непосредственно на Ninject).