ASP.NET Core 支持依赖注入, 也推荐使用依赖注入。 主要作用是用来降低代码之间的耦合度

什么是控制反转?

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

其中最常见的方式叫做“依赖注入”(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)

什么是依赖注入?

这个概念分开来理解

1. 依赖, 当B类里要调用A类完成某个功能, 那么就可以说是B依赖于A.

打开网易新闻 查看更多图片

上面这种方式是很常见的, 但是并不符合依赖的原则。 依赖的原则是: 依赖于抽象,而不是具体的实现。 也就是B类不能直接依赖A类, 应该依赖A类的抽象接口.

2. 注入。 在这里C类不去实例化A类,而是通过其他人传递给我,我只用就好。简单来说就是别人对依赖创建实例化,我自己只负责使用,这个过程可以理解为注入。

在上面的依赖中讲过, 最好不要直接依赖实现,应该依赖抽象接口。 通过注入我们了解到, 我们不应该直接实例化依赖项,而应该别人创建, 我们只负责使用。 综合一下, 我们就将原来的使用方式改为以下方式

打开网易新闻 查看更多图片

ClassB就是我们常见的使用方式, ClassD就是我们使用依赖注入的使用方式。

如何在.net core 里使用依赖注入?

1. 创建抽象接口(过程略)

2. 实现抽象接口(过程略)

3. 在Startup类的ConfigureServices方法中注册服务

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient();
}

4. 在Controller中使用, 通过在构造函数中获取实例, 然后使用

以上就是一个简单的.net core 使用依赖注入的例子

如何选择服务的生命周期?

在上面的第三步, 在注册服务的时候我们使用的AddTransient , 除此之外还有 AddScoped,AddSingleton

AddTransient
暂时生存期服务 (AddTransient) 是每次从服务容器进行请求时创建的。这种生存期适合轻量级、 无状态的服务。

AddScoped 范围内
作用域生存期服务 (AddScoped) 以每个客户端请求(连接)一次的方式创建。
注意:在中间件内使用有作用域的服务时,请将该服务注入至 Invoke 或 InvokeAsync 方法。请不要通过构造函数注入进行注入,因为它会强制服务的行为与单一实例类似。有关详细信息,请参阅 写入自定义 ASP.NET Core 中间件。

AddSingleton 单例
单一实例生存期服务 (AddSingleton) 是在第一次请求时(或者在运行 Startup·ConfigureServices 并且使用服务注册指定实例时)创建的。每个后续请求都使用相同的实例。如果应用需要单一实例行为,建议允许服务容器管理服务的生存期。不要实现单一实例设计模式并提供用户代码来管理对象在类中的生存期。
注意:从单一实例解析有作用域的服务很危险。当处理后续请求时,它可能会导致服务处于不正确的状态。

什么是容器?

讲到这里可能大家会有个疑问.

依赖注入把依赖的创建交给了别人, 我们只负责使用, 那么这个谁创建, 在哪儿创建, 怎么管理?

这个就引发了一个新的概念--容器. 容器就是负责管理系统所有的依赖. 在我们.net core 有一个默认的容器, 专门用于管理这些依赖.

但是默认的容器在小型项目的时候够了,但是大型项目就不够了.

我们通过AddTransient这些方式去注册服务, 那么一个项目有非常多的这种服务, 每一个都注册,在startup这个里面就变得非常臃肿复杂. 这个时候我们需要替换原来的容器.

如何更换默认容器?

在这里我们介绍一种常用的第三方容器: AutoFac, .net core 版本使用的是3.1 其他版本会略有不同.

一. nuget安装 Autofac.Extensions.DependencyInjection

二. 修改 Program.cs 文件

添加一句

.UseServiceProviderFactory(new Autofac.Extensions.DependencyInjection.AutofacServiceProviderFactory())

三. 修改 Startup.cs

新增ConfigureContainer

public void ConfigureContainer(ContainerBuilder builder)
{// 方式一 默认注册
builder.RegisterType().As();//注册 类似默认容器的services.AddTransient();
}

上面这种方式是默认的注册, 类似.net core 自带的注册。 但是并不合适我们批量注册, 下面介绍一种扫描程序集的注册方式

在controller里使用的方式和以前一样

打开网易新闻 查看更多图片