1、前言

面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI)、控制反转(IOC)及其容器等概念。在学习Core依赖注入、服务生命周期之前,下面让我们先了解下依赖倒置原则(DIP)、依赖注入(DI)、控制反转(IOC)等概念,然后再深入学习Core依赖注入服务。

2、依赖倒置原则(Dependency Inversion  Principle, DIP

抽象不应该依赖于细节,细节应当依赖于抽象,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口。一般来讲,就是高层模块定义接口,低层模块负责具体的实现。针对接口编程而不是针对细节编程

3、什么是依赖注入(Denpendency Injection)

3.1、依赖

人与人之间都有依赖(尤其我,就是离不开女人哈哈)何况软件呢?所谓依赖就是:当一个类需要另一个类协作来完成工作的时候就产生了依赖。比如用户登录,我们在控制器中UserController要完成用户登录、注册、修改密码等等事情、其中操作到数据库的(登录)我们用EF来完成,这里我们封装了一个EFLogin,这里的UserController就有一个ILogin的依赖。需要知道的是这里依赖于一个抽象为不是具体的某一个实现,所以给EFLogin定义了一个接口ILogin抽象了EFLogin的行为

3.2、注入

注入体现的是一个IOC(控制反转的的思想)。

 public interface IUser
{
string BB();
}
public class User : IUser
{
public string BB()
{
return "LP整天只会BB";
}
}
public class ShowInfo
{
IUser user = new User();
public void UserBB()
{
user.BB();
}
}

当我们调用ShowInfo的时候,是通过IUser接口实例化一个User类去实现其方法的这叫控制正传, 但是大湿兄说,我们不应该创建User类,而是让调用者给你传递,于是你通过构造函数让外界把这两个依赖给你。把依赖的创建丢给其它人。自己只负责使用,其它人丢给你依赖的这个过程理解为注入其它人丢给你依赖的这个过程理解为注入。也叫控制反转(IOC)

public interface IUser
{
string BB();
}
public class User : IUser
{
public string BB()
{
return "LP整天只会BB";
}
} public class ShowInfo2
{
private readonly IUser _user;
public ShowInfo2 (IUser user)
{
_user = user;
}
public void UserBB()
{
_user.BB();
}
}

3.3、为什么要使用依赖注入?

使用依赖注入我们可以很好的管理类跟类之间的依赖,在我们设计应用程序的时候遵循这几原则,确保代码的可维护性和扩展性;另外在Core的架构中依赖注入提供了对象创建和生命周期管理的核心能力,各个组件之间的相互协作也是由依赖注入框架来实现的

4、服务生命周期

在ConfigureServices方法中的容器注册每个应用程序的服务,Asp.Core都可以为每个应用程序提供三种服务生命周期:
Transient(暂时):每次请求都会创建一个新的实例。这种生命周期最适合轻量级,无状态服务。
Scoped(作用域):在同一个作用域内只初始化一个实例 ,可以理解为每一个请求只创建一个实例,同一个请求会在一个作用域内。在Scooped的生存周期内,如果容器释放 它也就被释放了
Singleton(单例):整个应用程序生命周期以内只创建一个实例,后续每个请求都使用相同的实例。如果应用程序需要单例行为,建议让服务容器管理服务的生命周期,而不是在自己的类中实现单例模式。

为了演示生命周期和注册选项之间的差异,请考虑以下代码:

IGuid接口返回一个Guid

public interface IGuid
{
Guid GetGuid { get; }
}

接口IScopedService、ISingletonService、ITransientService、都继承接口IGuid

 public interface IScopedService:IGuid
{ }
public interface ISingletonService: IGuid
{ }
public interface ITransientService: IGuid
{ }
 GuidShow类继承接口IScopedService、ISingletonService、ITransientService
public class GuidShow : IScopedService, ISingletonService, ITransientService
{ public GuidShow() : this(Guid.NewGuid())
{
}
public GuidShow(Guid id)
{
GetGuid = id;
}
public Guid GetGuid { get; private set; } }

在Starup里面注册

public void ConfigureServices(IServiceCollection services)
{
#region//注册不同生命周期的服务
services.AddSingleton<ISingletonService, SingletonService>();
services.AddTransient<ITransientService, TransientService>();
services.AddScoped<IScopedService, ScopedService>();
#endregion
services.AddControllers();
}

在WeatherForecastController Api里写一个Api

FromServices就是从容器里面获取我们的对象 每个对象都获取两边来来对比每个生命周期是怎么样的
 [ApiController]
[Route("[controller]/[action]")]
//路由
//API
[HttpGet]
public string GetService(
[FromServices] IScopedService scoped1, [FromServices] IScopedService scoped2,
[FromServices] ITransientService transient1, [FromServices] ITransientService transient2,
[FromServices] ISingletonService singleton, [FromServices] ISingletonService singleton2)
{
Console.WriteLine();
Console.WriteLine(); Console.WriteLine($"作用域1-->{scoped1.GetGuid}");
Console.WriteLine($"作用域2-->{scoped2.GetGuid}"); Console.WriteLine();
Console.WriteLine();
Console.WriteLine($"瞬时1-->{transient1.GetGuid}");
Console.WriteLine($"瞬时2-->{transient2.GetGuid}"); Console.WriteLine();
Console.WriteLine();
Console.WriteLine($"单例1-->{singleton.GetGuid}");
Console.WriteLine($"单例2-->{singleton2.GetGuid}"); Console.WriteLine("===========分割线=====================");
Console.WriteLine();
Console.WriteLine(); return "成功";
}

修改应用程序启动

启动应用程序

可以看出来单例跟作用域的都是一样的Guid 只有瞬时的不一样  再次刷新浏览器

单例的没有改变所以

Transient(暂时):每次调用服务的时候都会创建一个新的实例

 Scoped(作用域):一次请求(Action)内对象实例是相同的,但每次请求会产生一个新实例。

Singleton(单例):首次请求初始化同一个实例,后续每次请求都使用同一个实例。相当于在整个应用Application中只实例化一次实例,常见的单例模式。

下面是其他的注册

  #region//工程模式注册 单例作用域、瞬时 都可以用
services.AddSingleton<ISingletonService>(s=> {
return new SingletonService();
});
   #region//尝试注册
//注册过了就不在注册了
//using Microsoft.Extensions.DependencyInjection.Extensions;
services.TryAddScoped<IScopedService, ScopedService>();
#endregion
#region//移除注册 移除所有IScopedService的注册 不同实现的
 services.RemoveAll<IScopedService>(); #endregion

注册泛型 先写一个泛型类

 public interface ITypeT<T>
{
}
public class TypeT<T> : ITypeT<T>
{
public T GetT { get; }
public TypeT(T getT)
{
this.GetT = getT;
}
}

创建一个api Test

[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
public ITypeT<IScopedService> _typeT;
public TestController(ITypeT<IScopedService> typeT)
{
_typeT = typeT;
} [HttpGet]
public string TestGet()
{
return _typeT.GetHashCode().ToString();
}
}

注册一下 里面具体的参数不用谢 实现的时候只要带入某个具体的类就可以了,第一个参数服务的额类型,第二个参数服务的实现类型

     services.AddScoped(typeof(ITypeT<>),typeof(TypeT<>));

地址栏输入https://localhost:5001/api/test/testGet

看断点

GetT他得到的是ScopedService

5、依赖注入的方式

5.1、构造函数注入

我们可以在定义的Controller中以构造函数注入的方式注入所需的服务。他的服务是大部分接口都需要的话就用它

public ITypeT<IScopedService> _typeT;
public TestController(ITypeT<IScopedService> typeT)
{
_typeT = typeT;
}

5.2、FromServices

上面的GetService就是这种方式注入的,这个服务只是在某一个接口下用FromServices

当然还有其他的注入方式就不在研究了。

原文链接:https://www.cnblogs.com/w5942066/p/12808405.html

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)的更多相关文章

  1. ASP.NET Core中如影随形的”依赖注入”[下]: 历数依赖注入的N种玩法

    在对ASP.NET Core管道中关于依赖注入的两个核心对象(ServiceCollection和ServiceProvider)有了足够的认识之后,我们将关注的目光转移到编程层面.在ASP.NET ...

  2. ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起

    我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点.由于前面两章已经涵盖了依赖注入在管道构建过程中以及管道在处理请求过程的应用,但是内 ...

  3. [ASP.NET Core 3框架揭秘] 依赖注入:控制反转

    ASP.NET Core框架建立在一些核心的基础框架之上,这些基础框架包括依赖注入.文件系统.配置选项和诊断日志等.这些框架不仅仅是支撑ASP.NET Core框架的基础,我们在进行应用开发的时候同样 ...

  4. [ASP.NET Core 3框架揭秘] 依赖注入[5]: 利用容器提供服务

    毫不夸张地说,整个ASP.NET Core框架是建立在依赖注入框架之上的.ASP.NET Core应用在启动时构建管道以及利用该管道处理每个请求过程中使用到的服务对象均来源于依赖注入容器.该依赖注入容 ...

  5. [ASP.NET Core 3框架揭秘] 依赖注入[8]:服务实例的生命周期

    生命周期决定了IServiceProvider对象采用怎样的方式提供和释放服务实例.虽然不同版本的依赖注入框架针对服务实例的生命周期管理采用了不同的实现,但总的来说原理还是类似的.在我们提供的依赖注入 ...

  6. [ASP.NET Core 3框架揭秘] 依赖注入[10]:与第三方依赖注入框架的适配

    .NET Core具有一个承载(Hosting)系统,承载需要在后台长时间运行的服务,一个ASP.NET Core应用仅仅是该系统承载的一种服务而已.承载系统总是采用依赖注入的方式来消费它在服务承载过 ...

  7. [ASP.NET Core 3框架揭秘] 依赖注入[9]:实现概述

    <服务注册>.<服务消费>和<生命周期>主要从实现原理的角度对.NET Core的依赖注入框架进行了介绍,接下来更进一步,看看该框架的总体设计和实现.在过去的多个版 ...

  8. [ASP.NET Core 3框架揭秘] 依赖注入[7]:服务消费

    包含服务注册信息的IServiceCollection集合最终被用来创建作为依赖注入容器的IServiceProvider对象.当需要消费某个服务实例的时候,我们只需要指定服务类型调用IService ...

  9. [ASP.NET Core 3框架揭秘] 依赖注入[6]:服务注册

    通过<利用容器提供服务>我们知道作为依赖注入容器的IServiceProvider对象是通过调用IServiceCollection接口的扩展方法BuildServiceProvider创 ...

随机推荐

  1. js 数组 随机排序

    方法一: function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1) + min) } fu ...

  2. 1044 Shopping in Mars (25分)(二分查找)

    Shopping in Mars is quite a different experience. The Mars people pay by chained diamonds. Each diam ...

  3. 【原创】Linux RCU原理剖析(一)-初窥门径

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  4. 数据挖掘 决策树 Decision tree

    数据挖掘-决策树 Decision tree 目录 数据挖掘-决策树 Decision tree 1. 决策树概述 1.1 决策树介绍 1.1.1 决策树定义 1.1.2 本质 1.1.3 决策树的组 ...

  5. .NET Core项目部署到Linux(Centos7)(一)前言

    目录 1.前言 2.环境和软件的准备 3.创建.NET Core API项目 4.VMware Workstation虚拟机及Centos 7安装 5.Centos 7安装.NET Core环境 6. ...

  6. php--理解PHP的依赖注入和laravel的服务容器

    写在前面 为了了解laravel的服务容器在网上搜了许多文章,其中大多数都有其侧重点,没有很系统的一套东西以供参考,看完之后仍觉似乎少了一根把他们串起来的绳子,近期有幸拜读了陈昊的<Larave ...

  7. Docker的简介以及Dockerfile编写与使用

    Docker的简介 Docker是在容器的基础上,进行了进一步的封装,极大的简化了容器的创建和维护.使得Docker技术比虚拟机技术更为轻便.快捷. 下面是两张对比图. 可以看到传统虚拟机技术是虚拟出 ...

  8. orm层面的删除的注意事项

    orm层面的删除 当两张表的外键约束设置为RESTRICT or ACTION时,在sql的层面上想要删除父级表的数据时吗,mysql会拒绝删除,但是 使用orm的delete还是会删除父级表的数据. ...

  9. Fastdfs文件系统扩容

    1.简介     FastDFS文件服务器在设计时,为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式.存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是 ...

  10. 01-css3之过渡

    一.介绍 过渡(transition)是CSS3中具有颠覆性的特征之一,我们可以在不使用 Flash 动画或 JavaScript 的情况下,当元素从一种样式变换为另一种样式时为元素添加效果,经常和 ...