Ninject绑定不同的实现

时间:2012-06-11 22:36:21

标签: c# .net ninject

我一直在使用Ninject很短的时间,我正在试图弄清楚如何使用app.config / web.config条目做一些我在Unity中完成的事情。

我很确定这很简单,只是没有找到实现它的最佳方法,当然Ninject没有最好的文档。

我希望接口有不同的实现,而代码没有变化 - 特定的应用程序知道要使用哪种实现。

例如,当我使用Unity时,我会有一个实时应用程序和一个单元测试库,使用不同的数据库。所以:

var repo = IoC.Get<IRepository>();

会在我的实时应用中返回RealRepository,并在我的单元测试中返回FakeRepository。我只是在app.config或web.config中映射类。

在Ninject中,既然您在代码中定义了映射,那么似乎没有办法决定您使用哪些实现(或哪个模块),除了代码 - 但当然完整的目的是我不要我不想具体说明我想要使用哪种实现。

这样做有好办法吗?我能想到的唯一方法是从配置文件中动态选择NinjectModule实现,但这感觉不对。

2 个答案:

答案 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,在这种情况下我可以创建一个单独的模块,或者只是在测试中动态重新绑定内核。