Каковы намерения модулей Ninject? - PullRequest
58 голосов
/ 13 января 2010

Я - полный новичок, чтобы спеть

Я разбирал чужой код и нашел несколько экземпляров модулей nInject - классов, которые являются производными от Ninject.Modules.Module, и имеют метод load, содержащий большую часть их кода.

Эти классы вызываются путем вызова метода LoadModule экземпляра StandardKernel и передачи ему экземпляра класса модуля.

Может быть, я здесь упускаю что-то очевидное, но в чем выгода от простого создания простого старого класса и вызова его метода, или, возможно, статического класса со статическим методом?

Ответы [ 3 ]

61 голосов
/ 13 января 2010

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

// some method early in your app's life cycle
public Kernel BuildKernel()
{
    var modules = new INinjectModule[] 
    {
        new LinqToSqlDataContextModule(), // just my L2S binding
        new WebModule(),
        new EventRegistrationModule()
    };
    return new StandardKernel(modules);
}

// in LinqToSqlDataContextModule.cs
public class LinqToSqlDataContextModule : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository>().To<LinqToSqlRepository>();
    }
}

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

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

public interface IInterfaceA {}
public interface IInterfaceB {}
public interface IInterfaceC {}

public class ClassA : IInterfaceA {}

public class ClassB : IInterfaceB
{
    public ClassB(IInterfaceA a){}
}

public class ClassC : IInterfaceC
{
    public ClassC(IInterfaceB b){}
}

Построение ClassC является проблемой на этом этапе, с множеством глубин интерфейсов. Гораздо проще просто запросить у ядра IInterfaceC.

var newc = ApplicationScope.Kernel.Get<IInterfaceC>();
9 голосов
/ 13 января 2010

Может быть, я упускаю что-то очевидное здесь, но какая польза от этого над созданием простого старого класса и вызывая его метод, или, возможно, статический класс со статическим методом?

Да, вы можете просто вызвать несколько операторов Bind<X>().To<Z>() для установки привязок без модуля.

Разница в том, что если вы поместите эти операторы в модуль, то:

  • IKernel.Load(IEnumerable<Assembly>) может динамически обнаруживать такие модули посредством отражения и загружать их.
  • привязки логически сгруппированы под именем; Вы можете использовать это имя, чтобы выгрузить их снова с IKernel.Unload(string)
3 голосов
/ 28 декабря 2011

Может быть, я упускаю что-то очевидное здесь, но в чем выгода от простого создания простого старого класса и вызова его метода, или, возможно, статического класса со статическим методом?

Для нас это возможность добавлять тесты позже очень легко. Просто переопределите несколько привязок с mockobjects и вуаля ..... на устаревшем коде без DI, который подключил "все", почти невозможно начать вставлять тестовые случаи без некоторой переделки. С DI на месте И до тех пор, пока он использовался должным образом там, где DI все подключил, это очень просто сделать даже с устаревшим кодом, который может быть очень уродливым.

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

...