我一直在使用Ninject很短的时间,我正在试图弄清楚如何使用app.config / web.config条目做一些我在Unity中完成的事情。
我很确定这很简单,只是没有找到实现它的最佳方法,当然Ninject没有最好的文档。
我希望接口有不同的实现,而代码没有变化 - 特定的应用程序知道要使用哪种实现。
例如,当我使用Unity时,我会有一个实时应用程序和一个单元测试库,使用不同的数据库。所以:
var repo = IoC.Get<IRepository>();
会在我的实时应用中返回RealRepository
,并在我的单元测试中返回FakeRepository
。我只是在app.config或web.config中映射类。
在Ninject中,既然您在代码中定义了映射,那么似乎没有办法决定您使用哪些实现(或哪个模块),除了代码 - 但当然完整的目的是我不要我不想具体说明我想要使用哪种实现。
这样做有好办法吗?我能想到的唯一方法是从配置文件中动态选择NinjectModule实现,但这感觉不对。
答案 0 :(得分:8)
听起来您错过了使用IoC容器作为服务定位器。这给你带来很多问题。其中之一是测试要困难得多。我建议改为做正确的做构造函数注意而不是服务位置。
这意味着代替
public class MyClass
{
public void Do()
{
var repo = IoC.Get<IRepository>();
....
}
}
你做
public class MyClass
{
private IRepository repo;
public MyClass(IRepository repo)
{
this.repo = repo;
}
public void Do()
{
....
}
}
只有一个获取应用程序的根目录。其他一切都通过构造函数传递。
它使测试变得非常简单:
var testee = new MyClass(new Mock<IRepository>());
答案 1 :(得分:2)
您的实时应用和您的单元测试库是否有不同的端点?一个可能是一个单元测试项目(nunit?),另一个是应用程序,(console,windows或asp.net)。
每种类型的应用程序都应该独立定义它们的绑定,通常是通过定义单独的模块(您传递给StandardKernel
的构造函数)。一组为您的真实应用程序提供映射,另一组为您的单元测试提供映射。后者可能是必需的,也可能不是必需的 - 理想情况下,您正在测试的特定类的依赖关系应该很容易被模拟并传入,而根本不使用Ninject。在实践中,我找到了很多借口仍然可以使用Ninject,在这种情况下我可以创建一个单独的模块,或者只是在测试中动态重新绑定内核。