.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();
}
  1. 首先创建一个服务(对象)容器
  2. 把需要服务容器管理的服务(对象)添加到服务容器
  3. 通过服务容器构建一个 ServiceProvider(服务提供器),ServiceProvider 可以提供容器管理的服务(已添加到容器的服务)
  4. 通过 ServiceProvider(服务提供器)获取需要的服务(对象)

DI 的生命周期

Transient(瞬态)

使用一次即销毁,下次使用将是一个新的对象

Singleton(单例)

顾名思义,参考单例模式

Scoped(范围)

在一个范围内使用同一个对象

可以通过ServiceProviderCreateScope方法创建新的范围:

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)(一)相关推荐

  1. 理解AngularJS中的依赖注入

    作者 CraftsCoder 冷月无声 - 博客频道 - CSDN.NET http://blog.csdn.net/jaytalent/article/details/50986402 本文结合一些 ...

  2. 依赖倒置(DIP),控制反转(IoC)与依赖注入(DI)

    DIP,IoC与DI概念解析 依赖倒置 DIP(Dependency Inversion Principle) DIP的两大原则: 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象. 2.抽象不 ...

  3. Angular 中的依赖注入link

    Angular 中的依赖注入link 依赖注入(DI)是一种重要的应用设计模式. Angular 有自己的 DI 框架,在设计应用时常会用到它,以提升它们的开发效率和模块化程度. 依赖,是当类需要执行 ...

  4. 控制反转(Ioc)和依赖注入(DI)

    控制反转IOC, 全称 "Inversion of Control".依赖注入DI, 全称 "Dependency Injection". 面向的问题:软件开发 ...

  5. 控制反转IOC与依赖注入DI

    为什么80%的码农都做不了架构师?>>>    1. IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最 ...

  6. python ioc di_PHP的依赖注入(DI) 和 控制反转(IoC)

    要想理解 PHP 依赖注入 和 控制反转 两个概念,就必须搞清楚如下的两个问题:DI -- Dependency Injection 依赖注入 IoC -- Inversion of Control ...

  7. SAP Spartacus 中的依赖注入 Dependency Injection 介绍

    先了解 Angular 中的依赖注入 依赖项是指某个类执行其功能所需的服务或对象.依赖项注入(DI)是一种设计模式,在这种设计模式中,类会从外部源请求依赖项而不是让类自己来创建它们. Angular ...

  8. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  9. ASP.NET Core - 在ActionFilter中使用依赖注入

    上次ActionFilter引发的一个EF异常,本质上是对Core版本的ActionFilter的知识掌握不够牢固造成的,所以花了点时间仔细阅读了微软的官方文档.发现除了IActionFilter.I ...

  10. ASP.NET Core 中的依赖注入

    什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要依赖于抽象,不要依赖于具体.而控制反转(Ioc)就是这样的原则的其中一个实现思路, 这个思路的其中一种实现方式就是依赖 ...

最新文章

  1. Django学习记录-1
  2. matlab算法时间复杂度,关于降低算法时间复杂度问题的探讨和总结
  3. Oracle分析函数三——SUM,AVG,MIN,MAX,COUNT
  4. django的模板系统过滤器笔记
  5. sql 备份 文件大小_预测SQL备份大小
  6. Android中activity的生命周期
  7. Debian Squeeze 安装
  8. Linux中用户管理详解(上)-Linux学习日记
  9. java HTML5 学习资料汇总
  10. Java网络编程详解
  11. 【华为OD机试真题 JS】解压报文
  12. matlab修改证件照背景颜色
  13. matlab局部放大找交点,11.matlab找两条离散曲线的交点
  14. 嵌入式研发人员核心竞争力分析
  15. paranoid用法
  16. 如何查看一个期刊是sci几区以及影响因子 入藏号 ISSN等信息
  17. 高维空间中点到超平面的距离
  18. IDEA 运行 springboot运行出现 错误: 找不到或无法加载主类和找不到资源文件类
  19. Win10 安装 UG10.0 UG8.5教程 --(及安装错误问题解决)--NX 8.5 NX 10.0 安装教程
  20. ODOO11报价单确认订单创建入库单(_run_move)

热门文章

  1. 重庆核磁共振波谱仪做化合物结构鉴定
  2. heic格式转化器:heic转jpg
  3. 部署一个基于ChatGPT的微信聊天机器人以及产生的思考
  4. android图像识别建筑物轮廓,高分辨率遥感影像的建筑物轮廓信息提取方法
  5. m基于AlexNet神经网络和GEI步态能量图的步态识别算法MATLAB仿真
  6. leetcode:224周赛:5655. 重新排列后的最大子矩阵(中等)
  7. GDC2016 Lighting the City of Glass - Rendering Mirror's Edge Catalyst
  8. 网站设置为可信任站点
  9. 【数字图像处理】基于opencv的图像采集与拼接
  10. 股票的阿尔法收益和贝塔收益