.NET6最通俗易懂的依赖注入与控制反转

这是一个关于 ASP.NET 6 依赖注入的系列文章。

在这个系列中,我们将了解到什么是依赖注入、控制反转,它能够做什么,以及我们为什么要使用它。

之后,我们会进一步了解 ASP.NET 6 依赖注入的生命周期、服务容器等重要概念。.

最后,我们再深入了解服务作用域和更多的服务注册与注入方式。

.NET6最通俗易懂的依赖注入与控制反转

概述

依赖注入是 ASP.NET 框架的核心。

它主要提供两个核心功能:

  1. 「注册类型」,这些注册到依赖注入系统的类型,在 .NET 中有一个高大上的名字——服务。

    因为这些类型都是为了给系统提供某种服务,所以类型注册也叫服务注册。

  2. 「解析实例」,服务/类型被注册以后,就可以被同样注入到依赖注入系统中的其它服务/类型使用。

    如类型 A 依赖类型 B,类型 A 就可以通过依赖注入获取类型 B 的实例。

想要彻底理解依赖注入,我们就必须要对控制反转有所了解。

控制反转

依赖注入中有一个叫做容器的东西,也被称为 IoC(Inversion of Control - 控制反转)容器。

这个容器中保存着所有由依赖注入系统创建的实例,那么它为什么叫 IoC 容器呢?

「控制反转(IoC)是一种反转流、依赖和接口的方式,它把传统上由程序代码直接操控的对象的调用权交给第三方,通过第三方来实现对象组件的装配和管理。」

假设我们有这么一个场景,一个四、五岁的小朋友,想要吃东西。

如果他自己从冰箱里找东西吃,可能会造成一些不好的结果,比如可能会拿到无法直接直接食用的食物,或者忘记关冰箱门等灯。

.NET6最通俗易懂的依赖注入与控制反转

你可以思考一下,一个四、五岁的小孩儿,自己去冰箱拿食物,甚至自己去加工食材,你是不是觉得这不太正常?

那么正常情况是什么样的呢?

作为一个四、五岁的小孩儿,只需要找父母陈述一下需求,比如"我饿了、我想吃XX",这个时候,父母就会做好他所需要的食物,然后拿给他。

从主动去冰箱拿(正转)食物,到你想要吃的食物而被动获得(反转),这其实就是一个对象调用权转移的过程。

前者是主动获取食物,后者是由父母,也就是第三方把食物给他,而他并不关心食物从哪来,以及怎么得来。

所谓的“控制反转”的概念就是「对组件对象控制权的转移,从程序代码本身转移到了代码之外的第三方。」

通俗地说,就是应用程序的用户代码不负责依赖对象的创建和维护,而是将它交给第三方来负责,这样控制权就由应用程序转移到了第三方,即控制权实现了所谓的反转。

例如类型 A 需要使用类型 B 的实例,类型 B 实例的创建并不由类型 A 自己来负责,而是通过第三方来创建。

那么它和依赖注入又有什么关系呢?

依赖注入

「依赖注入是 IoC 的一种实现方式,用来实现依赖的反转。」

在前面的场景中,一个四、五岁的小孩,想要吃东西。

他只需要陈述一下需求,父母就会做好他需要的食物(依赖),然后拿给他(注入)。

依赖注入不是目的,它只是实现控制反转的方式。

使用依赖注入的目的,是为了管理应用中复杂的依赖关系,它可以帮助我们开发出松散耦合、可维护、可测试的代码和程序。

现在,再让我们回顾一下控制反转的解释。

一种反转流、依赖和接口的方式,它把传统上由程序代码直接操控的对象的调用权交给第三方,通过第三方来实现对象组件的装配和管理。

这个描述中的第三方就是依赖注入中的控制系统。

IoC 容器

在小孩子吃东西的场景里,有一方扮演着 IoC 容器的角色,你们分析下是谁?

我想很多人的第一直觉是“父母”?

其实,不严谨的来说,冰箱才是扮演 IoC 容器的角色,父母则是扮演依赖注入中控制系统的角色。

IoC 容器是依赖注入中一个保存已创建实例的东西,如果实例已创建,并且具有有效的生命周期,那么控制系统会直接从 IoC 容器获取实例,否则才会创建实例。

冰箱中的东西,都是父母买回来放进去的,同样也需要他们从冰箱中拿出来。

「所谓依赖注入系统,本质上就是一个实现了类型注册、实例解析和实例生命周期管理的组件。」

关于生命周期的内容,我们会在该系列的下一篇文章中详细讨论。

如果你了解工厂模式,那么你可以简单的把为依赖注入系统看作是一个超级工厂。

.NET6最通俗易懂的依赖注入与控制反转

在 .NET 的依赖注入系统中,所有注册的类型,都被称为服务。

ASP.NET 中的组件,大都都需要通过依赖注入获取它所依赖的服务实例。

所以说整个 ASP.NET 框架,都是建立在依赖注入系统之上的,这也是开发 ASP.NET 应用的最基本的编程模式。