跟我一起学.NetCore之依赖注入
前言
现阶段而言,依赖注入相关组件如果不会用一两个,感觉在Code的世界里肯定是落伍了,最起码得有工厂模式的思想,知道这样做的好处;提及到依赖注入,通常会关联出两个概念:Ioc(控制反转)和DI(依赖注入)
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
个人理解:
IoC(控制反转): 就是将原先的new对象这个操作交由第三方容器,由容器统一创建对象并管理其创建对象的生命周期;
DI(依赖注入): 我理解其中“依赖”有两层意思:
-
类与类之间的依赖关系;
-
对象的创建依赖于容器;
"注入":不用主动从容器中获取对象,由容器根据对象依赖关系自动注入;
依赖注入:程序将对象控制权交给容器,统一依赖容器创建对象,类之间的依赖,也是通过容器自动注入;
注:注入的前提是要把对象的控制权交给容器;
依赖注入优点:
-
轻松管理类及类之间的依赖;
-
减少代码耦合性;
-
提高代码维护性和可扩展性;
-
由容器统一创建对象和管理生命周期;
好了,先不详细深究了,这里先说说.NetCore中自带的依赖注入框架怎么玩;
正文
先看看.NetCore中的自带的依赖注入怎么用,先创建一个Asp.NetCore 程序:
上图是模板程序,只在Action 方法中直接使用了模板中已经注入好_logger的对象,此对象通过构造函数的形式注入,刚开始接触的Asp.NetCore的小伙伴会疑问,都没注册对应服务,怎么会注入,其实在我们启动过程的时候简单说到过,框架会自动注入一些默认的服务,其中就用ILogger,用起来就是这么简单;
.NetCore中依赖注入有几个关键的类型,简单介绍一下:
-
IServiceCollection:负责存储注册的服务,可以通过其扩展方法进行服务注册;
-
ServiceDescriptor:服务注册时的信息,如服务类型、实现类型、实例类型、生命周期等;
-
IServiceProvider: 理解是常说的容器,是IServiceCollection创建出来的,用来提供实例的;
-
IServiceScope:表示一个容器的子容器的生命周期;
通过以上可以简要理解注入的简要过程:
通过容器创建的出来的对象,根据不同的注入方式有以下三种生命周期:
-
Singleton(单例) :整个根容器的生命周期内是同一个对象;通过 services.AddSingleton()方法进行注册;
-
Scoped(作用域) :在容器或子容器的生命周期内,对象保持一致,如果容器释放掉,那就意味着对象也会释放掉;通过 services.AddScoped()方法进行注册;
-
Transient(瞬时) : 每次使用都会创建新的实例;通过 services.AddTransient()方法进行注册;
注:services 是 IServiceCollection services ;
以下通过程序演示常用的注入方法及其对应的生命周期;在以上创建的项目中针对不同的生命周期添加不同的类型,里面没有任何代码,如下图;
在Startup文件的ConfigureServices方法中进行注册,如下:
注册完毕之后,在Controller中的Action方法就可以使用了,如下:
通过对比每个对象的HashCode, 如果一样就代表是同一个对象,运行程序看结果(这里以项目的形式运行,在控制台中方便看输出):
以上实例只是常规注册方式,还有以下常用注册方式,如下图;
新增一个IUserService,方便后续演示
Asp.NetCore自带依赖注入的注册方式,如下:
增加一个Action方法,打了个断点运行调试:
其他注入方式就不一一运行演示了,这里主要演示排他注册的结果,如下:
所以结果成立
IUserService和IStudentService都注册了三次,但最终通过排他注册方式,最后成功的只一个和两个;
泛型注册方式,提供模板注册,如下:
先定义一个泛型:
注册,只能通过参数的形式注册:
使用放方式和上面一样;
依赖注入其他操作:
两种常用注入方式:
构造函数注入:当注入的服务对象多个地方使用时,就用构造函数的形式注入;
[FromService]注入:当只是临时使用服务对象时,就用[FromService]注入;
总结
.NetCore自带的注入常用用法差不多就这些,下一节说说作用域及容器创建对象之后的释放;