.Net 中使用依赖注入(DI)(一)
.Net 中使用 DI
依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式。
依赖注入简化模块的组装过程,降低模块之间的耦合度
为什么使用DI?
假设有这样的接口和实现类:
public interface ISayHello
{public void SayHello();
}public class Chinese : ISayHello, IDisposable
{public void SayHello(){Console.WriteLine("你好!");}public void Dispose(){Console.WriteLine("资源释放了");}
}
调用方式:
ISayHello sayHello = new Chinese();
sayHello.SayHello();
基于接口编程自有其好处,但是如上面的方式还是有缺陷的。调用者必须知道是谁实现了ISayHello
接口的SayHello
方法。这里就需要知道一个接口,一个实现类,加上本身调用的地方,一个简单的调用就有三者耦合。
DI 原理
下面让我们通过 DI 的方式实现,首先是 nuget 安装:
Install-Package Microsoft.Extensions.DependencyInjection -Version 6.0.0
上面包是微软实现的实现了依赖注入的包,看看怎么使用(最麻烦的使用方式):
ServiceCollection serviceContainer = new ServiceCollection(); // 构建一个服务容器
serviceContainer.AddTransient<Chinese>(); // 把 Chinese 作为瞬态服务(对象),添加到服务器容器// 通过容器构建一个 ServiceProvider(服务提供器),ServiceProvider 可以提供容器中管理的服务(已添加到容器的服务)
using (ServiceProvider serviceProvider = serviceContainer.BuildServiceProvider())
{ISayHello sayHello = serviceProvider.GetService<Chinese>(); // 从 ServiceProvider 中获取需要的服务(对象)sayHello.SayHello();
}
- 首先创建一个服务(对象)容器
- 把需要服务容器管理的服务(对象)添加到服务容器
- 通过服务容器构建一个 ServiceProvider(服务提供器),ServiceProvider 可以提供容器管理的服务(已添加到容器的服务)
- 通过 ServiceProvider(服务提供器)获取需要的服务(对象)
DI 的生命周期
Transient(瞬态)
使用一次即销毁,下次使用将是一个新的对象
Singleton(单例)
顾名思义,参考单例模式
Scoped(范围)
在一个范围内使用同一个对象
可以通过ServiceProvider
的CreateScope
方法创建新的范围:
ServiceCollection serviceContainer = new ServiceCollection();
serviceContainer.AddScoped<Chinese>();using (ServiceProvider serviceProvider = serviceContainer.BuildServiceProvider())
{ISayHello sayHello1 = serviceProvider.GetService<Chinese>();ISayHello sayHello2 = serviceProvider.GetService<Chinese>();ISayHello sayHello3 = null; // 应该在 Scope 范围内声明变量ISayHello sayHello4 = null; // 应该在 Scope 范围内声明变量ISayHello sayHello5 = null; // 应该在 Scope 范围内声明变量ISayHello sayHello6 = null; // 应该在 Scope 范围内声明变量using (IServiceScope serviceScope = serviceProvider.CreateScope()){sayHello3 = serviceScope.ServiceProvider.GetService<Chinese>();sayHello4 = serviceScope.ServiceProvider.GetService<Chinese>();}using (IServiceScope serviceScope = serviceProvider.CreateScope()){sayHello5 = serviceScope.ServiceProvider.GetService<Chinese>();sayHello6 = serviceScope.ServiceProvider.GetService<Chinese>();}Console.WriteLine(Object.ReferenceEquals(sayHello1, sayHello2)); // True, 都是通过 serviceProvider 创建Console.WriteLine(Object.ReferenceEquals(sayHello3, sayHello4)); // True, 都是通过同一个 serviceScope 创建,在单独的一个范围中Console.WriteLine(Object.ReferenceEquals(sayHello1, sayHello4)); // False,在单独的一个范围中,所以和 serviceProvider 创建的不一致Console.WriteLine(Object.ReferenceEquals(sayHello5, sayHello6)); // True, 同 sayHello3, sayHello4Console.WriteLine(Object.ReferenceEquals(sayHello1, sayHello6)); // False,同 sayHello1, sayHello4Console.WriteLine(Object.ReferenceEquals(sayHello4, sayHello6)); // False,在两个 serviceScope 中,所以 False
}
为了确保对象正确的生命周期,应该在 Scope 范围内声明变量
由上图可以知道,如果实现类实现了 IDisposable
接口,则在离开作用域之后,容器会自动调用对象的Dispose
方法。
也印证了需要在范围内声明并使用对象,在外面可能资源被释放了
如何选择生命周期?
如果一个类是无状态的,这时可以选择 Singleton。因为无状态的类无所谓并发问题(不会修改状态)。
如果一个类有状态,并且有 Scope 控制,可以注册为 Scoped。因为 Scope 控制的代码都是运行在同一个线程中的,没有并发修改的问题。
最后 Transient 在使用时,需要谨慎,因为每次都会创建一个新的对象。
.Net 中使用依赖注入(DI)(一)相关推荐
- 理解AngularJS中的依赖注入
作者 CraftsCoder 冷月无声 - 博客频道 - CSDN.NET http://blog.csdn.net/jaytalent/article/details/50986402 本文结合一些 ...
- 依赖倒置(DIP),控制反转(IoC)与依赖注入(DI)
DIP,IoC与DI概念解析 依赖倒置 DIP(Dependency Inversion Principle) DIP的两大原则: 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象. 2.抽象不 ...
- Angular 中的依赖注入link
Angular 中的依赖注入link 依赖注入(DI)是一种重要的应用设计模式. Angular 有自己的 DI 框架,在设计应用时常会用到它,以提升它们的开发效率和模块化程度. 依赖,是当类需要执行 ...
- 控制反转(Ioc)和依赖注入(DI)
控制反转IOC, 全称 "Inversion of Control".依赖注入DI, 全称 "Dependency Injection". 面向的问题:软件开发 ...
- 控制反转IOC与依赖注入DI
为什么80%的码农都做不了架构师?>>> 1. IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最 ...
- python ioc di_PHP的依赖注入(DI) 和 控制反转(IoC)
要想理解 PHP 依赖注入 和 控制反转 两个概念,就必须搞清楚如下的两个问题:DI -- Dependency Injection 依赖注入 IoC -- Inversion of Control ...
- SAP Spartacus 中的依赖注入 Dependency Injection 介绍
先了解 Angular 中的依赖注入 依赖项是指某个类执行其功能所需的服务或对象.依赖项注入(DI)是一种设计模式,在这种设计模式中,类会从外部源请求依赖项而不是让类自己来创建它们. Angular ...
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- ASP.NET Core - 在ActionFilter中使用依赖注入
上次ActionFilter引发的一个EF异常,本质上是对Core版本的ActionFilter的知识掌握不够牢固造成的,所以花了点时间仔细阅读了微软的官方文档.发现除了IActionFilter.I ...
- ASP.NET Core 中的依赖注入
什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要依赖于抽象,不要依赖于具体.而控制反转(Ioc)就是这样的原则的其中一个实现思路, 这个思路的其中一种实现方式就是依赖 ...
最新文章
- Django学习记录-1
- matlab算法时间复杂度,关于降低算法时间复杂度问题的探讨和总结
- Oracle分析函数三——SUM,AVG,MIN,MAX,COUNT
- django的模板系统过滤器笔记
- sql 备份 文件大小_预测SQL备份大小
- Android中activity的生命周期
- Debian Squeeze 安装
- Linux中用户管理详解(上)-Linux学习日记
- java HTML5 学习资料汇总
- Java网络编程详解
- 【华为OD机试真题 JS】解压报文
- matlab修改证件照背景颜色
- matlab局部放大找交点,11.matlab找两条离散曲线的交点
- 嵌入式研发人员核心竞争力分析
- paranoid用法
- 如何查看一个期刊是sci几区以及影响因子 入藏号 ISSN等信息
- 高维空间中点到超平面的距离
- IDEA 运行 springboot运行出现 错误: 找不到或无法加载主类和找不到资源文件类
- Win10 安装 UG10.0 UG8.5教程 --(及安装错误问题解决)--NX 8.5 NX 10.0 安装教程
- ODOO11报价单确认订单创建入库单(_run_move)
热门文章
- 重庆核磁共振波谱仪做化合物结构鉴定
- heic格式转化器:heic转jpg
- 部署一个基于ChatGPT的微信聊天机器人以及产生的思考
- android图像识别建筑物轮廓,高分辨率遥感影像的建筑物轮廓信息提取方法
- m基于AlexNet神经网络和GEI步态能量图的步态识别算法MATLAB仿真
- leetcode:224周赛:5655. 重新排列后的最大子矩阵(中等)
- GDC2016 Lighting the City of Glass - Rendering Mirror's Edge Catalyst
- 网站设置为可信任站点
- 【数字图像处理】基于opencv的图像采集与拼接
- 股票的阿尔法收益和贝塔收益