Каково намерение модулей 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 (оставляя остальную проводку на месте). Это могут быть системные тесты больше, чем единичные тесты, но я предпочитаю тесты более высокого уровня, чем средний разработчик, поскольку он проверяет интеграцию между классами, и это отличная документация для тех, кто присоединяется к проекту и может видеть всю функцию в действии (вместо этого просто частей функции) без необходимости установки целой системы).