C# Ninject 模块的意图是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2056409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the intention of Ninject modules?
提问by Jonathan
I'm a complete newbie to ninject
我是 ninject 的完全新手
I've been pulling apart someone else's code and found several instances of nInject modules - classes that derive from Ninject.Modules.Module, and have a load method that contains most of their code.
我一直在拆解别人的代码,发现了几个 nInject 模块的实例——从 Ninject.Modules.Module 派生的类,并且有一个包含大部分代码的 load 方法。
These classes are called by invoking the LoadModule method of an instance of StandardKernel and passing it an instance of the module class.
通过调用 StandardKernel 实例的 LoadModule 方法并将模块类的实例传递给它来调用这些类。
Maybe I'm missing something obvious here, but what is the benefit of this over just creating a plain old class and calling its method, or perhaps a static class with a static method?
也许我在这里遗漏了一些明显的东西,但是与仅仅创建一个普通的旧类并调用它的方法,或者一个带有静态方法的静态类相比,这有什么好处?
采纳答案by Jarrett Meyer
The Ninject modules are the tools used to register the various types with the IoC container. The advantage is that these modules are then kept in their own classes. This allows you to put different tiers/services in their own modules.
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>();
}
}
Having multiple modules allows for separation of concerns, even within your IoC container.
拥有多个模块允许分离关注点,即使在您的 IoC 容器中也是如此。
The rest of you question sounds like it is more about IoC and DI as a whole, and not just Ninject. Yes, you could use static Configuration objects to do just about everything that an IoC container does. IoC containers become really nice when you have multiple hierarchies of dependencies.
其余的问题听起来更多的是关于 IoC 和 DI 的整体,而不仅仅是 Ninject。是的,您可以使用静态 Configuration 对象来完成 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 is a pain at this point, with multiple depths of interfaces. It's much easier to just ask the kernel for an IInterfaceC.
在这一点上构建 ClassC 是一件痛苦的事情,有多种深度的接口。向内核询问 IInterfaceC 会容易得多。
var newc = ApplicationScope.Kernel.Get<IInterfaceC>();
回答by Wim Coenen
Maybe I'm missing something obvious here, but what is the benefit of this over just creating a plain old class and calling its method, or perhaps a static class with a static method?
也许我在这里遗漏了一些明显的东西,但是与仅仅创建一个普通的旧类并调用它的方法,或者一个带有静态方法的静态类相比,这有什么好处?
Yes, you can just call a bunch of Bind<X>().To<Z>()
statements to setup the bindings, without a module.
是的,您可以只调用一堆Bind<X>().To<Z>()
语句来设置绑定,而无需模块。
The difference is that if you put these statements in a module then:
不同之处在于,如果将这些语句放在一个模块中,则:
IKernel.Load(IEnumerable<Assembly>)
can dynamically discover such modules through reflection and load them.- the bindings are logically grouped together under a name; you can use this name to unload them again with
IKernel.Unload(string)
IKernel.Load(IEnumerable<Assembly>)
可以通过反射动态发现这些模块并加载它们。- 绑定在一个名称下在逻辑上组合在一起;您可以使用此名称再次卸载它们
IKernel.Unload(string)
回答by Dean Hiller
Maybe I'm missing something obvious here, but what is the benefit of this over just creating a plain old class and calling its method, or perhaps a static class with a static method?
也许我在这里遗漏了一些明显的东西,但是与仅仅创建一个普通的旧类并调用它的方法,或者一个带有静态方法的静态类相比,这有什么好处?
For us, it is the ability to add tests at a later time very easily. Just override a few bindings with mockobjects and voila.....on legacy code without a DI that wired "everything" up, it is near impossible to start inserting test cases without some rework. With a DI in place AND as long as it was used properly where the DI wired everything up, it is very simple to do so even on legacy code that may be very ugly.
对我们来说,它是能够很容易地在以后添加测试。只需用模拟对象覆盖一些绑定,瞧.....在没有将“一切”连接起来的 DI 的遗留代码上,几乎不可能在不进行一些返工的情况下开始插入测试用例。有了 DI 并且只要在 DI 连接所有内容的地方正确使用它,即使在可能非常丑陋的遗留代码上,这样做也非常简单。
In many DI frameworks, you can use the production module for your test with a test module that overrides specific bindings with mockobjects(leaving the rest of the wiring in place). These may be system tests more than unit tests, but I tend to prefer higher level tests than the average developer as it tests the integration between classes and it is great documentation for someone who joins the project and can see the whole feature in action(instead of just parts of the feature) without having to setup a whole system).
在许多 DI 框架中,您可以使用生产模块进行测试,并使用测试模块覆盖模拟对象的特定绑定(保留其余的接线)。这些可能是系统测试而不是单元测试,但我倾向于比普通开发人员更喜欢更高级别的测试,因为它测试类之间的集成,对于加入项目并可以看到整个功能运行的人来说,这是很好的文档(而不是部分功能)而无需设置整个系统)。