关于c#:依赖注入容器有什么意义?

What is the point of dependency injection container?

本问题已经有最佳答案,请猛点这里访问。

使用.NET核心,您可以注册"服务",正如我所理解的,这意味着您可以将类型注册到具体的类中。

因此,我决定是时候学习和练习DI了。我理解这个概念,通过测试它是非常有益的。然而,让我困惑的是注册服务的想法以及它是否真的需要。

例如,如果我有:

1
2
3
4
5
6
7
public class MyClass
{
    public MyClass(IDataContext)
    {
         ... store it
    }
}

这意味着我可以注入任何实现IDataContext的类,允许在测试中使用Fake和MoQ。但是,为什么我要注册一个服务并将IDataContext映射到启动中的一个具体类?在其他方法中使用以下方法是否有问题:

1
2
DataContext dc = new DataContext(); // concrete
var c = new MyClass(dc);

编辑

这个问题围绕使用容器(服务)而不是为什么在构造函数中使用接口。


现在你输入此码的那些类别

1
2
3
4
5
6
7
8
9
public class MyService
{
    public void DoSomething()
    {
        DataContext dc = new DataContext(); // concrete
        var c = new MyClass(dc);
        c.DoSomething();
    }
}

DataContextMyClass有很大的依赖。所以你不能在隔离中测试EDOCX1班级不应该在乎其他班级是如何做他们所做的,他们只应该在乎他们所说的他们要做的。这就是我们使用接口的原因This is separation of concerns.一旦你做到了这一点,你就可以在隔离中测试任何代码,而不取决于外部代码的行为。

在一个位置上登记你的依赖性也是清洁的,也就是说,你可以通过改变一个位置来交换依赖性,而不是忽视所有的习惯和改变它们。

在我的代码中,以MyService为例,要求使用DataContextMyClass。Instead,it should be like this:

ZZU1

总之,这不需要担心,因为这不是他的工作。但它需要一些富尔菲尔斯·埃多克斯1〔8〕的东西,但它不在乎它是如何实现的。现在可以在不取决于其他代码行为的情况下测试单元。

如果你不使用一个集装箱来处理依赖性,那么你很可能将依赖性引入到你的班级中,从而在第一个位置上保护整个编码点。

隔离测试很重要。如果你的测试超过了一个有限的密码部分,那不是一个测试单位。这是一个整合测试(它对不同的原因有自己的价值)。单位测试使它快速而容易地检验一个有限的代码工具包。当一个单位的测试没有经过时,你知道问题在哪里,而不必寻找它。因此,如果一个单元的测试取决于其他类型,或甚至其他系统(如本案中的DataContext是特定的数据库),那么我们就无法测试MyService。这意味着数据库必须在一个特定的状态下进行测试,这意味着测试不等于一次不等于一次不等于一次的测试。

为了进一步了解情况,我建议你观察深度沉淀到依赖性注射和写作的质量代码和可测试的软件。如果你要使用new来创建一个物体的实例,你已经把事情紧密地联系在一起了。依靠注射是你能避免的一种模式。这不是每次都很糟糕,我用new为Poco模型感到舒适。


控制反转(指构造一个物体)

这种模式的思想是,当您想要构造一个对象时,您只需要知道该对象的类型,而不需要知道它的依赖项或参数。

依赖注入

例如,通过使您能够直接将对象注入到构造函数中,该模式进一步反转了控制模式。

同样,您只需要知道要获取的对象的类型,依赖容器将注入一个对象。

您也不需要知道是否构造了一个新对象,或者是否获得了一个完全就绪的现有引用。

最常用的依赖项注入类型是构造函数注入,但您可以将类型注入其他地方,如方法。

关注点分离

通常,您通过接口注册一个类型,以消除对该类型的依赖。

这对于测试时模拟类型非常有帮助,并且有助于使用开闭原则。

Martin Fowler关于"控制容器倒置和依赖注入模式"。


是的,您可以手动创建所有实例。在小项目中,这是一种惯例。项目中链接类的地方称为组合根,您所做的是构造函数注入。

IOC图书馆可以简化这段代码,特别是考虑到复杂的情况,如生命周期范围和组注册。


你可以用手动注射你的依赖性。但这是一项非常艰巨的任务。如果你的服务大了,你会越来越依赖它,每一个依赖它自己的地方都会有多个依赖。

如果你改变了你的依赖性,你需要调整所有的习惯。一个集装箱的主要优点之一是,集装箱将完全依赖于解决问题。无需手工作业。只要注册服务,并在你想要的地方使用,以及你经常想要的。

对于小项目来说,这似乎太过头了,但如果你的项目增长了一点,你会很欣赏的。

对于固定依赖性,与之密切相关,而不想改变,注射手工操作很精细。

使用一个集装箱有另一个优势。集装箱将控制其服务的生命周期。一个服务可以是一个单词,一个瞬时(每一个请求都会有一个新的程序)或有一个分数的生活时间。

例如,如果你有一个跨行动的工作流程。镜头可以对准交易。While in the transaction,requests to a service will return the same instance.

下一个交易将打开一个新的范围,然后将有新的实例。这让你有机会进行一次交易或进行一次交易,但要防止此后交易使用的资源来自前者。