ASP.NET Core服务生命周期

1.前言

在ConfigureServices方法中的容器注册每个应用程序的服务,Asp.Core都可以为每个应用程序提供三种服务生命周期:

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

2.服务生命周期与注册选项案例演示

为了演示生命周期和注册选项之间的差异,请考虑以下接口,将任务表示为具有唯一标识符 OperationId 的操作。根据以下接口配置操作服务的生命周期的方式,容器在类请求时提供相同或不同的服务实例:

public interface IOperation
{
    Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}

上面四种服务接口在 Operation 类中实现。调用Operation类时将自动生成一个GUID,下面是Operation类的实现:

public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
{
    public Operation() : this(Guid.NewGuid())
    {
    }
    public Operation(Guid id)
    {
        OperationId = id;
    }
    public Guid OperationId { get; private set; }
}

再注册一个OperationService服务实例,当通过依赖关系注入请求 OperationService 实例时,它将接收每个服务的新实例或基于从属服务(Operation)的生命周期的现有实例。OperationService 服务作用就是第二次调用 Operation类,查看Operation类实例的作用域变化。

public class OperationService
{
    public OperationService(
        IOperationTransient transientOperation,
        IOperationScoped scopedOperation,
        IOperationSingleton singletonOperation,
        IOperationSingletonInstance instanceOperation)
    {
        _transientOperation = transientOperation;
        _scopedOperation = scopedOperation;
        _singletonOperation = singletonOperation;
        _singletonInstanceOperation = instanceOperation;
    }
    public IOperationTransient _transientOperation { get; }
    public IOperationScoped _scopedOperation { get; }
    public IOperationSingleton _singletonOperation { get; }
    public IOperationSingletonInstance _singletonInstanceOperation { get; }
}

然后在Startup.ConfigureServices()服务容器中注册各个生命周期的实例:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IOperationTransient, Operation>();
    services.AddScoped<IOperationScoped, Operation>();
    services.AddSingleton<IOperationSingleton, Operation>();
    services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
    // OperationService depends on each of the other Operation types.
    services.AddTransient<OperationService, OperationService>();
}

再在IndexModel模块里面调用OnGet方法输出,观察IOperation与OperationService类属性OperationId 值的变化:

public class IndexModel : PageModel
{
    public OperationService _operationService { get; }
    public IOperationTransient _transientOperation { get; }
    public IOperationScoped _scopedOperation { get; }
    public IOperationSingleton _singletonOperation { get; }
    public IOperationSingletonInstance _singletonInstanceOperation { get; }
    public IndexModel(
    OperationService operationService,
    IOperationTransient transientOperation,
    IOperationScoped scopedOperation,
    IOperationSingleton singletonOperation,
    IOperationSingletonInstance singletonInstanceOperation)
    {
        _operationService = operationService;
        _transientOperation = transientOperation;
        _scopedOperation = scopedOperation;
        _singletonOperation = singletonOperation;
        _singletonInstanceOperation = singletonInstanceOperation;
    }
    public void OnGet()
    {
        Console.WriteLine("IOperation操作:");
        Console.WriteLine("暂时:" + _transientOperation.OperationId.ToString());
        Console.WriteLine("作用域:" + _scopedOperation.OperationId.ToString());
        Console.WriteLine("单例:" + _singletonOperation.OperationId.ToString());
        Console.WriteLine("实例:" + _singletonInstanceOperation.OperationId.ToString());
        Console.WriteLine("OperationService操作:");
        Console.WriteLine("暂时:" + _operationService._transientOperation.OperationId.ToString());
        Console.WriteLine("作用域:" + _operationService._scopedOperation.OperationId.ToString());
        Console.WriteLine("单例:" + _operationService._singletonOperation.OperationId.ToString());
        Console.WriteLine("实例:" + _operationService._singletonInstanceOperation.OperationId.ToString());
    }
}

执行IndexModel 类输出结果:

由图总结如下:
2.1 Transient(暂时):每次调用服务的时候都会创建一个新的实例。即在IndexModel类的局部方法或属性中(这里是OnGet方法)实例化一个依赖对象Operation类,伪代码是:

public class IndexModel: PageModel
{
    public void OnGet()
    {
          //调用IndexModel类时,实例化了两次Operation类
      //第一次
          OperationService operationService=new OperationService();
     //第二次
     IOperationTransient TransientOperation=new Operation();
    }
}

2.2 Scoped(作用域):一次请求(Action)内对象实例是相同的,但每次请求会产生一个新实例。相当于在IndexModel类的全局中实例化一次依赖对象Operation类,伪代码是:

OperationService operationService = null;
public IndexModel()
{
    operationService = new OperationService();
    operationService._scopedOperation = new Operation();
}
public void OnGet()
{
    operationService._scopedOperation.OperationId;
    IOperationScoped operationScoped = operationService._scopedOperation;
    operationScoped.OperationId
}

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

生命周期流程图如下:

到此这篇关于ASP.NET Core服务生命周期的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET Core依赖关系注入

    1.前言 面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI).控制反转(IOC)及其容器等老生常谈的概念,初学者很容易被这些概念搞晕(包括我在内),在学习Core依赖注入服务之前,下面让我们先了解下依赖倒置原则(DIP).依赖注入(DI).控制反转(IOC)等概念,然后再深入学习Core依赖注入服务. 2.依赖倒置原则(DIP) 高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口.通俗来讲,就是高层模块定义接口,低层模块负责实现.

  • ASP.Net Core中的内存和GC机制

    托管代码 在 .NET 中, CLR(Common Language Runtime) 负责提取托管代码并编译成机器语言,然后执行它.在此过程中,CLR 提供自动内存管理.安全边界.类型安全等服务,保证了代码安全. 托管代码指在其执行过程中由 CLR(Common Language Runtime) 管理的代码,托管代码是可在 .NET 上运行得一种高级语言(C#.F#等),编写的托管代码被编译后会被生成 中间语言(IL). CLR 有 .NET Core/.NET5+.Mono..NET Fr

  • ASP.Net Core中的日志与分布式链路追踪

    目录 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory ILoggerProvider ILogger Logging Providers 怎么使用 日志等级 Trace.Debug 链路跟踪 OpenTracing 上下文和跟踪功能 跟踪单个功能 将多个跨度合并到一条轨迹中 传播过程中的上下文 分布式链路跟踪 在不同进程中跟踪 在 ASP.NET Core 中跟踪 OpenTracing API 和

  • ASP.NET Core在WebApi项目中使用Cookie

    目录 一.Cookie的作用 二.在ASP.NET Core中使用Cookie 1.在控制器中直接使用Cookie 1.1.设置Cookie 1.2.获取Cookie 1.3.删除Cookie信息 2.封装Cookie 一.Cookie的作用 Cookie通常用来存储有关用户信息的一条数据,可以用来标识登录用户,Cookie存储在客户端的浏览器上.在大多数浏览器中,每个Cookie都存储为一个小文件.Cookie表示为键/值对的形式,可以利用键来读取.写入或删除Cookie. 在ASP.NET

  • ASP.NET Core应用启动Startup类简介

    1.前言 Core与早期版本的 ASP.NET 对比,配置应用程序的方式的 Global.asax.FilterConfig.cs和RouteConfig.cs 都被Program.cs 和 Startup.cs取代了.Program.cs作为Web应用程序的默认入口,在没有任何修改的情况下,会调用同目录下Startup.cs中的ConfigureServices 和 Configure方法. 2.Startup类 Startup类配置服务和应用的请求管道.Program.Main方法是应用程序

  • ASP.NET Core全局异常处理

    一.前言 在程序设计中,我们会遇到各种各样的异常问题,一个好的异常处理解决方案能够帮助开发者快速的定位问题,也能够给用户更好的用户体验.那么我们在AspNetCore中该如何捕获和处理异常呢?我们以一个WebApi项目为例,讲解如何捕获和处理异常. 二.异常处理 1.异常处理 开发过ASP.NET程序的人都知道:IExceptionFilter.这个过滤器同样在AspNetCore中也可以用来捕获异常.不过,对于使用IExceptionFilter,更建议使用它的异步版本:IAsyncExcep

  • ASP.NET Core使用NLog记录日志

    目录 一.前言 二.使用NLog 1.引入NLog 2.添加配置文件 3.在控制器中使用 4.读取指定位置的配置文件 5.封装 一.前言 在所有的应用程序中,日志功能是不可或缺的模块,我们可以根据日志信息进行调试.查看产生的错误信息,在ASP.NET Core中我们可以使用log4net或者NLog日志组件来实现记录日志的功能,这里讲解如何在ASP.NET Core中使用NLog. 这里采用的是.NET Core 3.1创建应用程序. 那么什么是NLog呢? NLog是一个基于.NET平台编写的

  • .NET Core分布式链路追踪框架的基本实现原理

    分布式追踪 什么是分布式追踪 分布式系统 当我们使用 Google 或者 百度搜索时,查询服务会将关键字分发到多台查询服务器,每台服务器在自己的索引范围内进行搜索,搜索引擎可以在短时间内获得大量准确的搜索结果:同时,根据关键字,广告子系统会推送合适的相关广告,还会从竞价排名子系统获得网站权重.通常一个搜索可能需要成千上万台服务器参与,需要经过许多不同的系统提供服务. 多台计算机通过网络组成了一个庞大的系统,这个系统即是分布式系统. 在微服务或者云原生开发中,一般认为分布式系统是通过各种中间件/服

  • ASP.NET Core服务生命周期

    1.前言 在ConfigureServices方法中的容器注册每个应用程序的服务,Asp.Core都可以为每个应用程序提供三种服务生命周期: Transient(暂时):每次请求都会创建一个新的实例.这种生命周期最适合轻量级,无状态服务. Scoped(作用域):在同一个作用域内只初始化一个实例 ,可以理解为每一个请求只创建一个实例,同一个请求会在一个作用域内. Singleton(单例):整个应用程序生命周期以内只创建一个实例,后续每个请求都使用相同的实例.如果应用程序需要单例行为,建议让服务

  • ASP.NET服务器控件的生命周期分析

    本文实例分析了ASP.NET服务器控件的生命周期.分享给大家供大家参考.具体如下: (1)初始化----在此阶段中,主要完成两项工作:一.初始化在传入Web请求生命周期内所需的设置:二.跟踪视图状态.首先,页面框架通过默认方式引发Init事件,并调用OnInit()方法,控件开发人员可以重写该方法为控件提供初始化逻辑.此后,页面框架将调用TrackViewState方法来跟踪视图状态.需要注意的是:多数情况下,Control基类提供的TrackViewState方法实现已经足够了.只有在控件定义

  • Vue.js与 ASP.NET Core 服务端渲染功能整合

    http://mgyongyosi.com/2016/Vuejs-server-side-rendering-with-aspnet-core/ 原作者:Mihály Gyöngyösi 译者:oopsguy.com 我真的很喜欢在前端使用 Vue.js,Vue 服务端渲染直到第二个版本才被支持. 在本例中,我想展示如何将 Vue.js  服务端渲染功能整合 ASP.NET Core. 我们在服务端使用了 Microsoft.AspNetCore.SpaServices 包,该包提供 ASP.N

  • ASP.NET Web页生命周期和执行的方法介绍

    以上所列的阶段中有些在页面级是不可见的,并且仅对服务器控件的编写者和要创建从 Page 导出的类的开发人员有意义.Init.Load.PreRender.Unload,再加上由嵌入式控件定义的所有回发事件,就构成了向外发送页面的各个阶段标记. 执行的各个阶段 页面生命周期中的第一个阶段是初始化.这个阶段的标志是 Init 事件.在成功创建页面的控件树后,将对应用程序触发此事件.换句话说,当 Init 事件发生时,.aspx 源文件中静态声明的所有控件都已实例化并采用各自的默认值.控件可以截取 I

  • Asp.Net Core中服务的生命周期选项区别与用法详解

    前言 最近在做一个小的Demo中,在一个界面上两次调用视图组件,并且在视图组件中都调用了数据库查询,结果发现,一直报错,将两个视图组件的调用分离,单独进行,却又是正常的,寻找一番,发现是配置依赖注入服务时,对于服务的生命周期没有配置得当导致,特此做一次实验来认识三者之间(甚至是四者之间的用法及区别). 本文demo地址(具体见WebApi控制器中):https://gitee.com/530521314/koInstance.git (本地下载)  一.服务的生命周期 在Asp.Net Core

  • 详解ASP.NET MVC的整个生命周期

    目录 一.介绍 二.MVC生命周期详述 View的初始化和渲染呈现 三.结束 一.介绍 我们做开发的,尤其是做微软技术栈的,有一个方向是跳不过去的,那就是MVC开发.我相信大家,做ASP.NET MVC 开发有的有很长时间,当然,也有刚进入这个行业的.无论如何,如果有人问你,你知道ASP.NET MVC的生命周期吗?你知道它的来世今生吗?你知道它和 ASP.NET WEBFORM 有什么区别吗?估计,这些问题,有很多人会答不上来,或者说不清楚.今天,我就把我的理解写出来,也是对我自己学习的一次回

  • 验证一个ASP.NET应用程序和页面的生命周期的实现代码

    如果我们能更好地掌握这样一个过程,那么对单个ASP.NET Page的生命周期也能更好地了解: 下面介绍如何编写一个简单的ASP.NET 页面和一个简单的HttpModule,对MSDN里提到的ASP.NET的生命周期进行验证 1. 首先使用Visual Studio 2010建立一个空的ASP.NET网站 (ASP.NET 4.0) 2. 添加一个Default.aspx,添加三个ASP.NET控件,分别为TextBox,Button和Validator: 复制代码 代码如下: <form i

  • 深入理解Asp.Net中WebForm的生命周期

    前言 本文主要给大家介绍的是关于Asp.Net中WebForm生命周期的相关内容,分享出来供大家参考学习,下面来看看详细的介绍: 一.Asp.Net页面生命周期的概念 当我们在浏览器地址栏中输入网址,回车查看页面时,这时会向服务器端IIS)发送一个request请求,服务器就会判断发送过来的请求页面,当完全识别 TTP页面处理程序类后,ASP.NET运行时将调用处理程序的 ProcessRequest 方法来处理请求.创建页面对象.通常情况下,无需更改此方法的实现,因为它是由 Page 类提供的

  • asp.net页面生命周期详解

    Asp.net是微软.Net战略的一个组成部分.它相对以前的Asp有了很大的发展,引入了许多的新机制.本文就Asp.net页面的生命周期向大家做一个初步的介绍,以期能起到指导大家更好.更灵活地操纵Asp.net的作用.当一个获取网页的请求(可能是通过用户提交完成的,也可能是通过超链接完成的)被发送到Web服务器后,这个页面就会接着运行从创建到处理完成的一系列事件.在我们试图建立Asp.net页面的时候,这个执行周期是不必去考虑的,那样只会自讨苦吃.然而,如果被正确的操纵,一个页面的执行周期将是一

  • IIS处理Asp.net请求和Asp.net页面生命周期详细说明

    ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维护状态.运行事件处理程序代码以及进行呈现.了解页生命周期非常重要,因为这样做您就能在生命周期的合适阶段编写代码,以达到预期效果.此外,如果您要开发自定义控件,就必须熟悉页生命周期,以便正确进行控件初始化,使用视图状态数据填充控件属性以及运行任何控件行为代码.(控件的生命周期基于页的生命周期,但是页引发的控件事件比单独的 ASP.NET 页中可用的事件多.) 一般来说,页要经

随机推荐