Каково намерение модулей Ninject?

Я полный новичок в ninject

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

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

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

 

Ответ 1

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

// some method early in your app 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){}
}

Building ClassC - это боль в этой точке, с несколькими глубинами интерфейсов. Намного проще просто спросить ядро ​​для IInterfaceC.

var newc = ApplicationScope.Kernel.Get<IInterfaceC>();

Ответ 2

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

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

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

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

Ответ 3

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

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

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