.Net Core3.0依赖注入DI

构建ASP.NET Core应用程序的时候,依赖注入已成为了.NET Core的核心,这篇文章,我们理一理依赖注入的使用方法。
不使用依赖注入
首先,我们创建一个ASP.NET Core Mvc项目,定义个表达的爱服务接口,中国小伙类实现这个类如下:
public interface ISayLoveService
{
string SayLove();
} public class CNBoyService : ISayLoveService
{
public string SayLove()
{
return "安红,我喜欢你";
}
}
在LoveController 控制器中调用 ISayLoveService的SayLove方法。
public class LoveController : Controller
{
private ISayLoveService loveService;
public IActionResult Index()
{
loveService = new CNBoyService(); //中国小伙对安红的表达
ViewData["SayLove"] = loveService.SayLove();
return View();
}
}
输出如图:

小结:LoveController控制器调用ISayLoveService服务的SayLove方法;我们的做法,直接在控制器去new CNBoyService()实例对象,也就是LoveController依赖ISayLoveService类。

思考:能不能有种模式,new实例不要在使用的时候进行创建,而是在外部或者有一个容器进行管理;这不就是ioc思想吗?好处,代码的解耦、代码更好的维护等等。
使用依赖注入
上面的疑惑,答案是肯定的,有!并且ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式(当然也可以兼容第三方)。我们还使用上面的代码,
服务注册
在Startup类ConfigureServices方法中注册服务容器中的依赖关系
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISayLoveService, CNBoyService>();
services.AddControllersWithViews();
}
在LoveControlle控制器中,通过构造函数注入
private readonly ISayLoveService loveService;
public LoveController(ISayLoveService loveService)
{ this.loveService = loveService;
} public IActionResult Index()
{
ViewData["SayLove"] = loveService.SayLove(); return View();
}
LoveController 正在将ISayLoveService作为依赖项注入其构造函数中,然后在Index方法中使用它。
推荐:
将注入的依赖项分配给只读字段/属性(以防止在方法内部意外为其分配另一个值)。
使用接口或基类抽象化依赖关系实现。
小结:在控制器中,还有几种使用如:[FromServices] 标签 、 HttpContext.RequestServices.GetService<T>();我们发现可以使用ASP.NET Core 提供了一个内置的服务容器 IServiceProvider。服务只需要在Startup.ConfigureServices 方法中注册,然后在运行时将服务注入 到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时对其进行处理。
思考:服务注册的时候使用的是 AddSingleton,如services.AddSingleton<ISayLoveService, CNBoyService>();还有其他的吗?
服务生命周期
服务注册的时候,ASP.NET Core支持指定三种生命周期如:
Singleton 单例
Scoped 范围
Transient 短暂的
Singleton 仅创建一个实例。该实例在需要它的所有组件之间共享。因此始终使用同一实例。
Scoped 每个范围创建一个实例。在对应用程序的每个请求上都会创建一个范围,因此每个请求将创建一次注册为Scoped的任何组件。
Transient 在每次被请求时都会创建,并且永不共享。
为了能够更好的裂解生命周期的概念,我们把上面代码稍作改动,做一个测试:
ISayLoveService 新增个属性LoveId,类型为guid,
public interface ISayLoveService
{
Guid LoveId { get; }
string SayLove();
}
public interface ITransientSayLoveService : ISayLoveService
{
}
public interface IScopedSayLoveService : ISayLoveService
{
}
public interface ISingletonSayLoveService : ISayLoveService
{
}
public interface ISingletonInstanceSayLoveService : ISayLoveService
{
}
BoyService也很简单,在构造函数中传入一个Guid,并对它进行赋值。
public class BoyService : ITransientSayLoveService,
IScopedSayLoveService,
ISingletonSayLoveService,
ISingletonInstanceSayLoveService
{
public BoyService():this(Guid.NewGuid()) { }
public BoyService(Guid id)
{
LoveId = id;
}
public Guid LoveId { get; private set; } public string SayLove()
{
return LoveId.ToString();
}
}
每个实现类的构造函数中,我们都产生了一个新的guid,通过这个GUID,我们可以判断这个类到底重新执行过构造函数没有.
服务注册代码如下:
public void ConfigureServices(IServiceCollection services)
{
//生命周期设置为Transient,因此每次都会创建一个新实例。
services.AddTransient<ITransientSayLoveService, BoyService>();
services.AddScoped<IScopedSayLoveService, BoyService>();
services.AddSingleton<ISingletonSayLoveService, BoyService>();
services.AddSingleton<ISingletonInstanceSayLoveService>(new BoyService(Guid.Empty)); services.AddControllersWithViews();
}
在LifeIndex方法中多次调用ServiceProvider的GetService方法,获取到的都是同一个实例。
public IActionResult LifeIndex()
{
ViewData["TransientSayLove1"] = HttpContext.RequestServices.GetService<ITransientSayLoveService>().SayLove();
ViewData["ScopedSayLove1"] = HttpContext.RequestServices.GetService<IScopedSayLoveService>().SayLove();
ViewData["SingletonSayLove1"] = HttpContext.RequestServices.GetService<ISingletonSayLoveService>().SayLove();
ViewData["SingletonInstanceSayLove1"] = HttpContext.RequestServices.GetService<ISingletonInstanceSayLoveService>().SayLove();
//同一个HTTP请求 ,在从容器中获取一次
ViewData["TransientSayLove2"] = HttpContext.RequestServices.GetService<ITransientSayLoveService>().SayLove();
ViewData["ScopedSayLove2"] = HttpContext.RequestServices.GetService<IScopedSayLoveService>().SayLove();
ViewData["SingletonSayLove2"] = HttpContext.RequestServices.GetService<ISingletonSayLoveService>().SayLove();
ViewData["SingletonInstanceSayLove2"] = HttpContext.RequestServices.GetService<ISingletonInstanceSayLoveService>().SayLove(); return View();
}
我们编写view页面,来展示这些信息如下:
@{
ViewData["Title"] = "LifeIndex";
}
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">Operations</h2>
</div>
<div class="panel-body">
<h3>获取第一次</h3>
<dl>
<dt>Transient1</dt>
<dd>@ViewData["TransientSayLove1"] </dd>
<dt>Scoped1</dt>
<dd>@ViewData["ScopedSayLove1"]</dd>
<dt>Singleton1</dt>
<dd>@ViewData["SingletonSayLove1"] </dd>
<dt>Instance1</dt>
<dd>@ViewData["SingletonInstanceSayLove1"]</dd>
</dl>
<h3>获取第二次</h3>
<dl>
<dt>Transient2</dt>
<dd>@ViewData["TransientSayLove2"]</dd>
<dt>Scoped2</dt>
<dd>@ViewData["ScopedSayLove2"]</dd>
<dt>Singleton2</dt>
<dd>@ViewData["SingletonSayLove2"]</dd>
<dt>Instance2</dt>
<dd>@ViewData["SingletonInstanceSayLove2"]</dd>
</dl>
</div>
</div>
</div>
运行代码第一次输出:

我们发现,在一次请求中,发现单例、范围的生命周期的guid 没有变化,说明分别用的是同一个对象,而瞬态guid不同,说明对象不是一个。
刷新之后,查看运行效果

我们发现通过刷新之后,单例模式的guid还是跟首次看到的一样,其他的都不同;
总结:如果您将组件A注册为单例,则它不能依赖已注册“作用域”或“瞬态”生存期的组件。一般而言:组件不能依赖寿命短于其寿命的组件。如果默认的DI容器不能满足项目需求,可以替换成第三方的如功能强大的Autofac。
.Net Core3.0依赖注入DI的更多相关文章
- Yii2.0 依赖注入(DI)和依赖注入容器的原理
依赖注入和依赖注入容器 为了降低代码耦合程度,提高项目的可维护性,Yii采用多许多当下最流行又相对成熟的设计模式,包括了依赖注入(Denpdency Injection, DI)和服务定位器(Serv ...
- 05、NetCore2.0依赖注入(DI)之Web应用启动流程管理
05.NetCore2.0依赖注入(DI)之Web应用启动流程管理 在一个Asp.net core 2.0 Web应用程序中,启动过程都做了些什么?NetCore2.0的依赖注入(DI)框架是如何管理 ...
- 06、NetCore2.0依赖注入(DI)之整合Autofac
06.NetCore2.0依赖注入(DI)之整合Autofac 除了使用NetCore2.0系统的依赖注入(DI)框架外,我们还可以使用其他成熟的DI框架,如Autofac.Unity等.只要他们支持 ...
- 07、NetCore2.0依赖注入(DI)之生命周期
07.NetCore2.0依赖注入(DI)之生命周期 NetCore2.0依赖注入框架(DI)是如何管理注入对象的生命周期的?生命周期有哪几类,又是在哪些场景下应用的呢? -------------- ...
- ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下
ADO.NET 一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data → DataTable, ...
- 控制反转(Ioc)和依赖注入(DI)
控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...
- 控制反转IOC与依赖注入DI【转】
转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...
- 依赖注入(DI)和Ninject
[ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject 本文目录: 1.为什么需要依赖注入 2.什么是依赖注入 3.使用NuGet安装库 4.使用Ninject的一般步骤 5. ...
- iOS控制反转(IoC)与依赖注入(DI)的实现
背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大 ...
随机推荐
- 记一个复杂组件(Filter)的从设计到开发
此文前端框架使用 rax,全篇代码暂未开源(待开源) 原文链接地址:Nealyang/PersonalBlog 前言 貌似在面试中,你如果设计一个 react/vue 组件,貌似已经是司空见惯的问题了 ...
- 2018年蓝桥杯java b组第七题
标题:螺旋折线 如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次. 对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度. 例如dis(0, ...
- Android Studio [相对布局RelativeLayout]
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...
- Android Studio [水平布局LinearLayout]
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- OpenGl 实现鼠标分别移动多个物体 ----------移动一个物体另外一个物体不动--读取多个3d模型操作的前期踏脚石
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11620088.html 前言: 因为接下来的项目需求是要读取多个3D模型,并且移动拼接,那么我 ...
- 阿里云服务器CentOS6.9安装Tomcat
上篇讲了CentOS6.9安装jdk,这篇来讲Tomcat的安装,本来准备使用yum命令安装的,但是通过 yum search tomcat 发现只有tomcat6,所以就在官网下了一个tomcat8 ...
- JavaScript实现各种排序算法
前言:本文主要是用JavaScript实现数据结构中的各种排序算法,例如:插入排序.希尔排序.合并排序等. 冒泡排序 function bubbleSort(arr) { console.time(& ...
- 用OllyDbg爆破一个小程序
用OllyDbg爆破一个小程序 一.TraceMe小程序 TraceMe是对用户名.序列号判断是否合法的一个小程序.我们任意输入一组用户名.序列号进行check判断,结果如下: 二.用OllyDbg对 ...
- XCTF-web2
这种题目是比较简单地..直接写个小脚本就行了2333 <?php $a=" a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2Z ...
- jsp JavaBean el表达式
JSP三大指令 一个jsp页面中,可以有0~N个指令的定义! 1. page --> 最复杂:<%@page language="java" info="xx ...