目录:

一、什么是依赖注入

1.1、什么是依赖?

1.2、 什么是注入?

1.3、依赖注入解决的问题

二、服务的生命周期(.Net Core DI)

三、替换默认服务容器

  3.1、为什么替换默认服务容器?

  3.2、如何替换服务容器

 

一、什么是依赖注入

1、 什么是依赖

Rely类
public class Rely { public Task Test(string testMessage) {
Console.WriteLine(testMessage);return Task.FromResult(0); }   }
 

Output类
public class Output { Rely rely = new Rely(); public async Task Out() { await
rely.Test("這是一個測試消息"); } }
Output类需要Rely类来帮助它实现输出的功能,这样Output类对Rely类产生了依赖,可以理解为Output依赖于Rely

依赖的一个设计原则:依赖于抽象,而不是具体的实现,这个后面会具体解释的

 

2、 什么是注入

修改Output类
public class Output { private Rely _rely; public Output(Rely rely) { _rely =
rely; }public async Task Out() { await _rely.Test("這是一個測試消息"); } }
在这里Output类不去实例化Rely类,而是通过其他人传递给我,我只用就好。到底怎么理解注入呢?

简单来说就是别人对依赖创建实例化,我自己只负责使用,别人创建好了给我使用,这么一个过程可以理解为注入

这里主要体现了控制反转 (IoC)
<https://docs.microsoft.com/zh-cn/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#dependency-inversion>
的思想,什么是IOC ?我们看看下面的图就好理解了

 

 

 

直接依赖关系在运行的时候A调用B,B调用C,编译的时候A取决于B,B取决于C。

而在反转依赖关系中,
A可以调用B实现的抽象上的方法,让A可以在运行时调用B,而B又在编译时依赖于A控制的接口,程序运行时流程跟直接依赖关系一样。但是插入了接口意味着可以轻松的有不同实现

 

3、 依赖注入解决的问题


依赖注入主要体现了IOC思想,IOC将实现详细信息编写为依赖并且实现了更高级的抽象,因此程序测试性,维护性,模块化程度都更高了。这也就对应了刚刚的那个设计规则--依赖于抽象,而不是具体的实现。

那么依赖注入到底解决了哪些问题呢?

问题一:在直接依赖关系中如果A类需要更换为其他实现,那么就必须得修改B类

问题二:如果有多个依赖B类的类,那么将会实例化多个配置,这样代码会比较分散和冗余

问题三:这种实现方法很难实现单元测试

解决这些问题的办法:

一:使用了接口抽象话依赖关系的实现,改动实现只需要改动注入的地方即可

二:注册服务容器中的依赖关系,有多处需要不许多出实例化配置,直接在Startup.ConfigureServices中注册即可

 

二、服务的生命周期(.Net Core DI)

在.NET Core中DI的核心分为两个组件:IServiceCollection和 IServiceProvider。

*
*   IServiceCollection---负责注册
*   IServiceProvider---负责提供实例
 

在Startup.cs中ConfigureServices中注册服务
public void ConfigureServices(IServiceCollection services) { services.Configure
<CookiePolicyOptions>(options => { // This lambda determines whether user
consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded= context => true; options.MinimumSameSitePolicy =
SameSiteMode.None; }); services.AddSingleton<IHttpContextAccessor,
HttpContextAccessor>();//单例生存期 services.AddScoped<IHttpContextAccessor,
HttpContextAccessor>();//范围生存期 services.AddTransient<IHttpContextAccessor,
HttpContextAccessor>();//暂时生存期
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
 

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

暂时生存期会在每次请求的时候创建一个实例

2、 Scoped(范围生存期)--范围生存期服务是每个客户端连接时创建的一次实例

范围生存期会在客户端连接时创建一次实例,然后每次请求的实例都是相同的

3、 Singleton(单例生存期)--单例生存期会在程序第一次请求是创建一次实例

单例生存期仅会在第一次连接时创建一次实例,所有整个程序使用的实例都是同一个实例

 

三、替换默认服务容器

1、 为什么替换默认服务容器


我们可以首先理解下什么是服务容器—依赖注入把依赖的创建给了别人,别人创建好了再给我们使用。那么在哪里创建依赖呢?或者说在那里管理依赖呢?这里就有了容器这个概念,负责管理系统中所有的依赖。

那么我们为什么要替换容器呢?


内置的服务容器足够实现一些小型的项目或满足大多数的消费者,但是遇到大型的项目就比较麻烦了,依赖较多,内置的服务容器就显得有点短板了。当我们遇到这些问题的时候就可以考虑替换默认服务容器。

2、 如何替换服务容器

这里我们说下替换服务容器为Autofac <https://autofac.org/>。

安装适当的包

*
*   Autofac
*   Autofac.Extensions.DependencyInjection
在 Startup.ConfigureServices 中配置返回 为IServiceProvider:
public IServiceProvider ConfigureServices(IServiceCollection services) {
services.AddMvc();// Add other framework services // Add Autofac var
containerBuilder =new ContainerBuilder(); containerBuilder.RegisterModule
<DefaultModule>(); containerBuilder.Populate(services); var container =
containerBuilder.Build();return new AutofacServiceProvider(container); }
 

如果要使用第三方容器的话, Startup.ConfigureServices 必须返回 IServiceProvider。

然后我们在 DefaultModule 中配置 Autofac
public class DefaultModule : Module { protected override void
Load(ContainerBuilder builder) { builder.RegisterType
<CharacterRepository>().As<ICharacterRepository>(); } }
 

 

 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信