// 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>();
}
}
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){}
}
3 回答
对我们来说,能够很容易地在以后添加测试 . 只需用mockobjects覆盖一些绑定,然后在没有连接“一切”的DI的情况下对遗留代码进行覆盖,几乎不可能在没有一些返工的情况下插入测试用例 . 使用DI并且只要在DI连接所有内容的情况下正确使用它,即使在可能非常难看的遗留代码上也很简单 .
在许多DI框架中,您可以使用 生产环境 模块进行测试,使用测试模块覆盖与mockobjects的特定绑定(保留其余的布线) . 这些可能是系统测试而不是单元测试,但我倾向于比普通开发人员更喜欢更高级别的测试,因为它测试了类之间的集成,对于加入项目并可以看到整个功能的人来说,它是很好的文档(而不是只需部分功能)而无需设置整个系统) .
是的,您可以调用一堆
Bind<X>().To<Z>()
语句来设置绑定,而无需模块 .不同之处在于,如果您将这些语句放在一个模块中,那么:
IKernel.Load(IEnumerable<Assembly>)
可以通过反射动态发现这些模块并加载它们 .绑定在名称下逻辑分组在一起;您可以使用此名称再次使用
IKernel.Unload(string)
卸载它们Ninject模块是用于向IoC容器注册各种类型的工具 . 优点是这些模块然后保存在他们自己的类中 . 这允许您在自己的模块中放置不同的层/服务 .
拥有多个模块可以分离关注点,即使在您的IoC容器中也是如此 .
你们其他人的问题听起来更像是IoC和DI作为一个整体,而不仅仅是Ninject . 是的,您可以使用静态配置对象来执行IoC容器所做的所有事情 . 当您有多个依赖关系层次结构时,IoC容器变得非常好 .
在这一点上构建ClassC是一种痛苦,具有多个接口深度 . 要求内核提供IInterfaceC要容易得多 .