# 模块二 基础巩固 依赖注入

## 2.2.1 核心模块--依赖注入 <a href="#id-221-he-xin-mo-kuai-yi-lai-zhu-ru" id="id-221-he-xin-mo-kuai-yi-lai-zhu-ru"></a>

* 什么是依赖注入
* .NET Core DI 生命周期
* 服务设计
* 服务范围检查

ASP.NET Core 依赖注入：<https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0>

### 什么是依赖注入 <a href="#shen-me-shi-yi-lai-zhu-ru" id="shen-me-shi-yi-lai-zhu-ru"></a>

Dependency injection 依赖注入

Inversion of Control 控制反转

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FFfvkrM3Sq9CW89CCAPi1%2F185.jpg?alt=media\&token=abdbc434-a10c-4a68-b008-2be80be32389)

#### 依赖注入 与 依赖查找 <a href="#yi-lai-zhu-ru-yu-yi-lai-cha-zhao" id="yi-lai-zhu-ru-yu-yi-lai-cha-zhao"></a>

依赖注入：通过编排告诉 IOC 容器整个内部类之间的依赖关系

依赖查找：通过回调或者上下文获取依赖

#### asp .net core 如何实现 <a href="#aspnetcore-ru-he-shi-xian" id="aspnetcore-ru-he-shi-xian"></a>

在上一小节新建的 HelloApi 项目中修改 Program.cs

```
namespace HelloApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            Console.WriteLine("Server started");

            // 依赖查找
            var helloService = host.Services.GetRequiredService<IHelloService>();
            helloService.Hello();

            host.Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((ctx,services)=>
                {
                    // 依赖注入
                    // 任何时候获取到的都是一个新的实例
                    services.AddTransient<IHelloService, HelloService>();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}
```

IHelloService

```
namespace HelloApi.Services
{
    public interface IHelloService
    {
         void Hello();
    }
}
```

HelloService

```
namespace HelloApi.Services
{
    public class HelloService : IHelloService
    {
        public void Hello()
        {
            Console.WriteLine("hello dotnet core");
        }
    }
}
```

### .NET Core DI 生命周期 <a href="#netcoredi-sheng-ming-zhou-qi" id="netcoredi-sheng-ming-zhou-qi"></a>

```
// 依赖注入
// 任何时候获取到的都是一个新的实例
services.AddTransient<IHelloService, HelloService>();
// 每个 scope 都有一个实例
services.AddScoped<IHelloService, HelloService>();
// 单例，整个应用程序的生命周期只有一个实例
services.AddSingleton<IHelloService, HelloService>();
```

#### 通过 id 区分不同的服务生命周期 <a href="#tong-guo-id-qu-fen-bu-tong-de-fu-wu-sheng-ming-zhou-qi" id="tong-guo-id-qu-fen-bu-tong-de-fu-wu-sheng-ming-zhou-qi"></a>

HelloService

```
private string _id;

public HelloService()
{
    _id = Guid.NewGuid().ToString();
}
```

Program.cs

```
// 依赖查找
var helloService1 = host.Services.GetRequiredService<IHelloService>();
helloService1.Hello();

var helloService2 = host.Services.GetRequiredService<IHelloService>();
helloService2.Hello();
```

启动程序，输出如下：

```
Server started
hello dotnet core: cc77ee85-3806-4c29-b693-8da8bcf40498
hello dotnet core: 3306bebc-2340-4645-82e7-0e15fac0e9c7
```

AddSingleton

Program.cs

```
.ConfigureServices((ctx,services)=>
{
    // 依赖注入
    // 单例，整个应用程序的生命周期只有一个实例
    services.AddSingleton<IHelloService, HelloService>();
})
```

启动程序，输出如下：

```
Server started
hello dotnet core: 35aa7646-e2bd-4d44-8f15-cd6aca3b0215
hello dotnet core: 35aa7646-e2bd-4d44-8f15-cd6aca3b0215
```

AddScoped

需要自定义一个 scope

Program.cs

```
using (var scope = host.Services.CreateScope())
{
    // 依赖查找
    var helloService1 = scope.ServiceProvider.GetRequiredService<IHelloService>();
    helloService1.Hello();

    var helloService2 = scope.ServiceProvider.GetRequiredService<IHelloService>();
    helloService2.Hello();
}
```

```
.ConfigureServices((ctx,services)=>
{
    // 依赖注入
    // 每个 scope 都有一个实例
    services.AddScoped<IHelloService, HelloService>();
})
```

启动程序，输出如下：

```
Server started
hello dotnet core: abf083e2-7914-43b9-8e7f-540381a05b37
hello dotnet core: abf083e2-7914-43b9-8e7f-540381a05b37
```

### 服务设计 <a href="#fu-wu-she-ji" id="fu-wu-she-ji"></a>

* 不要使用静态类和静态成员，不要使用全局状态，而改为使用全局单例类
* 不要在内部自己实例化对象
* 每一个服务应该尽可能地小、易创建、易测试

### 服务范围检查 <a href="#fu-wu-fan-wei-jian-cha" id="fu-wu-fan-wei-jian-cha"></a>

singleton 的服务不能依赖于 scoped 的服务

### GitHub源码链接： <a href="#github-yuan-ma-lian-jie" id="github-yuan-ma-lian-jie"></a>

<https://github.com/MingsonZheng/ArchitectTrainingCamp/tree/main/HelloApi>
