jk's notes
  • ch04 Minimal API 中的依赖注入

ch04 Minimal API 中的依赖注入

本章主要内容:

  1. 什么是依赖注入
  2. 在 Minimal API 项目中使用依赖注入

技术要求

介绍需要安装 .NET 的版本, 以及 Github 仓库中有示例代码.

什么是依赖注入

.NET 原生支持依赖注入, 又称 DI, 是一种软件设计模式.

DI 是控制反转的一种实现. 它是类与其依赖之间的一种设计模式. 而 .NET 中有大量的类都支持依赖注入, 例如日志, 配置等服务.

然后作者介绍了一下传统开发方式与 DI 模式的代码结构的区别.

这里略去细节.

传统需要某个类的实例, 则创建该类的实例, 然后再使用. 这样存在的问题在于:

  1. 一旦类发生修改, 每个使用的代码都需要再修改.
  2. 不易于单元测试

依赖注入的优势:

  1. 使用接口对依赖进行抽象
  2. 在 .NET 内置服务中注册依赖注入
  3. 使用构造器进行注入

然后作者对代码进行改良, 按照 DI 的写法来重写. 来说明这个修改很容易. 来说明迁移很简单.

然后使用 Services.AddScoped<> 来演示注册.

依赖注入的生命周期

前面我们介绍了, DI 的优势, 以及如何将之前的代码转换为 DI 的模式.

最后我们将我们的类添加到 .NET 的一个服务集合 (ServiceCollection) 中. 本节中我们将了解不同的服务的生命周期.

服务的生命周期是指,在容器中, 服务被创建出来后可以使用多久. 一旦注册, 依赖需要一个声明周期.

下面列表中定义了可用的生命周期:

  • Transient, 瞬时. 每次需要该实例的时候都会创建一个.
  • Scoped, 范围的. 在一个范围内每次使用时创建一个实例, 在同一个 HTTP 请求中会使用一个实例.
  • Signleton, 单例. 只在第一次需要实例的时候创建. 下一次使用时会复用该实例.

一般在 Web 开发中, 只会使用到前两种情况. 即 transient 和 scoped. 但是如果有需求, 并不会禁用单例的. 但这不是一个好的设计模式.

在瞬时与范围的模式下, 不使用对象后都会将对象销毁.

在 Minimal API 项目中实现依赖注入

作者直接使用 WebAPI 的模板来修改代码, 用温度计算的方式来演示.

这里了解到为什么说不好单测了.

就是说, 每次使用对象就需要 new 一个出来, 那么每一个 new 出来的对象本质上都不是同一个对象.

理论上说, new 的新对象与原始对象不是一个对象, 无法保证测试出来的结果是复核要求的, 至少需要保证, 在参数不变的情况下实例化出来的对象具有同等特性. 但是使用 DI 可以使用注入来保证是同一个对象.

然后作者展示了改造方法

  1. 定义接口, 定义接口方法来获得天气数据.
  2. 然后实现接口. 返回天气数据 (模板代码中使用硬编码, 这里抽象出接口后, 原则上, 数据源可以是任意的).
  3. 在 Program.cs 中执行 builder.Services.AddScoped<接口, 类>() 来完整注册. 即将对象添加到服务集合中了.
  4. 在需要使用的时候, 只需要通过 MapHandler 方法的参数来注入即可 (没有构造器, 直接用方法来注入).

例如:

app.MapGet("/test", (接口 注入的实例) => {...});

有些时候, 你可能需要在启动时的主函数中, 直接使用服务 (没有方法参数注入), 那么可以直接访问 服务集合的实例实现. 例如:

using (var scope = app.Services.CreateScope()) {
  var service = scope.ServiceProvider.GetRequiredService<接口>();
  ...
}

小结 (略)

Last Updated:
Contributors: jk