4

我使用 Ninject 已经有一段时间了,我正试图弄清楚如何使用 app.config/web.config 条目来完成我在 Unity 中所做的事情。

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

我想对一个接口有不同的实现,而代码没有变化——特定的应用程序知道要使用哪个实现。

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

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

RealRepository在我的实时应用程序中返回 a ,FakeRepository在我的单元测试中返回 a 。我会简单地映射我的 app.config 或 web.config 中的类。

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

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

4

2 回答 2

8

听起来您好像在误用 IoC 容器作为服务定位器。这给你带来了很多问题。其中之一是测试要困难得多。我建议改为正确执行构造函数 injsction 而不是服务位置。

这意味着而不是

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()
    {
        ....
    }
}

您的应用程序的根目录只有一个 Get。其他一切都通过构造函数传递。

它使测试变得非常简单:

var testee = new MyClass(new Mock<IRepository>());
于 2012-06-11T23:59:20.603 回答
2

您的实时应用程序和单元测试库没有不同的端点吗?一个可能是单元测试项目(nunit?),另一个是应用程序(控制台、windows 或 asp.net)。

每种类型的应用程序都应该独立定义它们的绑定,通常通过定义单独的模块(传递给 的构造函数StandardKernel)。一组为您的真实应用程序提供映射,另一组为您的单元测试提供映射。后者可能是必要的,也可能不是必要的——理想情况下,您正在测试的特定类的依赖项应该很容易模拟和传递,而根本不使用 Ninject。在实践中,我找到了许多仍然使用 Ninject 方便的借口,在这种情况下,我要么创建一个单独的模块,要么只是在测试本身中即时重新绑定内核。

于 2012-06-11T22:41:35.910 回答