欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

asp.net core 系列 4 注入服务的生存期

程序员文章站 2022-03-23 12:43:19
一.服务的生存期 在容器中每个注册的服务,根据程序应用需求都可以选择合适的服务生存期,ASP.NET Core 服务有三种生存期配置: (1) Transient:暂时生存期,在每次请求时被创建。 这种生存期适合轻量级的,无状态的服务。 (2) Scoped: 作用域生存期,在每次请求被创建一次。 ......

一.服务的生存期

  在容器中每个注册的服务,根据程序应用需求都可以选择合适的服务生存期,asp.net core 服务有三种生存期配置:

    (1) transient:暂时生存期,在每次请求时被创建。 这种生存期适合轻量级的,无状态的服务。

    (2) scoped: 作用域生存期,在每次请求被创建一次。

    (3) singleton: 单例生存期,在它们第一次被请求时创建。每个后续请求将使用相同的实例。如果应用程序需要单例行为,建议让服务容器管理服务的生命周期,而不是在自己的类中实现单例模式。

   1.1 演示案例

    为了演示生存期和注册选项之间的差异, 以下服务接口,任务是演示标识符 operationid 的操作值变化。 根据为以下接口配置操作服务的生存期的方式,容器在类请求时提供相同或不同的服务实例:

   public interface ioperation
    {
        guid operationid { get; }
    }
    //用于演示暂时生存期
    public interface ioperationtransient : ioperation
    {
    }
    //用于演示作用域生存期
    public interface ioperationscoped : ioperation
    {
    }
    //用于演示单例生存期
    public interface ioperationsingleton : ioperation
    {
    }
    //用于演示单例中空guid
    public interface ioperationsingletoninstance : ioperation
    {
    }

    上面四种服务接口在 operation 类中实现。 调用 operation类时将自动生成一个 guid(如果实例化operation类时没有指定guid),下面是operation类的实现:

 public class operation : ioperationtransient,
     ioperationscoped,
     ioperationsingleton,
     ioperationsingletoninstance
    {
        /// <summary>
        /// 构造方法中生成guid,在实例化类时
        /// </summary>
        public operation() : this(guid.newguid())
        {
        }

        public operation(guid id)
        {
            operationid = id;
        }

        /// <summary>
        /// 获取guid
        /// </summary>
        public guid operationid { get; private set; }
    }

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

    public class operationservice
    {

        public ioperationtransient transientoperation { get; }
        public ioperationscoped scopedoperation { get; }
        public ioperationsingleton singletonoperation { get; }
        public ioperationsingletoninstance singletoninstanceoperation { get; }


        public operationservice(
        ioperationtransient transientoperation,
        ioperationscoped scopedoperation,
        ioperationsingleton singletonoperation,
        ioperationsingletoninstance instanceoperation)
        {
            transientoperation = transientoperation;
            scopedoperation = scopedoperation;
            singletonoperation = singletonoperation;
            singletoninstanceoperation = instanceoperation;
        }
    }

    (1) 如果在请求时创建了临时服务(transient),则 ioperationtransient 服务的 operationid 与 operationservice 的 operationid 不同。 operationservice 将接收 ioperationtransient 类的新实例。 新实例将生成一个不同的 operationid。

    (2) 如果按请求创建有作用域的服务(scoped),则 ioperationscoped 服务的 operationid 与请求中 operationservice 的该 id 相同。 在请求中,两个服务共享不同的 operationid 值。

    (3) 如果单一实例服务(singleton),则只创建一次 并在所有请求和所有服务中使用,则 operationid 在所有服务请求中保持不变。

 

    下面是在 startup.configureservices 服务容器中注册,指定服务的生存期:

            services.addtransient<ioperationtransient, operation>();
            services.addscoped<ioperationscoped, operation>();
            services.addsingleton<ioperationsingleton, operation>();
            services.addsingleton<ioperationsingletoninstance>(new operation(guid.empty));

            services.addtransient<operationservice, operationservice>();

 

    为了演示各个请求中的对象生存期。 下面示例应用 index页面,请求 ioperation 类型和 operationservice。 然后查看operation类属性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 string bindguidmsg { get; set; }
        public void onget()
        {
            bindguidmsg += "ioperation操作: <br/> ";
            bindguidmsg += "暂时性:" + transientoperation.operationid.tostring() + "</br>";
            bindguidmsg += "有作用域:" + scopedoperation.operationid.tostring() + "</br>";
            bindguidmsg += "单一实例:" + singletonoperation.operationid.tostring() + "</br>";
            bindguidmsg += "实例:" + singletoninstanceoperation.operationid.tostring() + "</br>";

            bindguidmsg += "</br></br></br>operationservice操作:</br>";
            bindguidmsg += "暂时性:" + operationservice.transientoperation.operationid.tostring() + "</br>";
            bindguidmsg += "有作用域:" + operationservice.scopedoperation.operationid.tostring() + "</br>";
            bindguidmsg += "单一实例:" + operationservice.singletonoperation.operationid.tostring() + "</br>";
            bindguidmsg += "实例:" + operationservice.singletoninstanceoperation.operationid.tostring() + "</br>";
        }
    }
    <div >
        @{
          @html.raw(@model.bindguidmsg);  
        }
    </div>

 

    第一次index页面请求:

    ioperation 操作:
    暂时性:8ef874a3-743d-4288-98d4-3df126cd940d 
    有作用域:256ff050-f469-4ea3-8dde-16cdd3087c83 
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741 
    实例:00000000-0000-0000-0000 -000000000000 

    operationservice操作:
    暂时性:5411fd0d-f2e1-4885-beee-2d7ccf48dceb 
    有作用域:256ff050-f469-4ea3-8dde-16cdd3087c83 
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741 
    实例:00000000-0000-0000- 0000-000000000000

 

    第二次index页面请求:

    ioperation操作:
    暂时性:e685fd0e-d2e0-4900-9eff-e6bc41cd2f80
    有作用域:ca233b49-8326-4a7e-8ee4-6993d70786ed
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741
    实例:00000000-0000-0000-0000-000000000000

    operationservice操作:
    暂时性:db89be00-c3b7-4f99-bead-5be693ccc2c0
    有作用域:ca233b49-8326-4a7e-8ee4-6993d70786ed
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741
    实例:00000000-0000-0000-0000-000000000000

 

  下面再总结一下:

    (1)暂时性注册的服务,每次调用服务都会是一个新的服务对象实例。相当于在indexmodel类的局部(方法或属性中)实例化一个依赖对象operation类,伪代码是:

public class indexmodel
{
    public void onget()
        {
//加载index页时,实例化了二次operation类
         //第一次 operationservice operationservice=new operationservice();
         //第二次
         ioperationtransient transientoperation =new operation(); } }

    (2)作用域注册的服务,一次请求内(加载一次index页)对象实例是相同的,但每次请求会产生一个新实例。相当于在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
        }

    (3)单例注册的服务,实例对象对每个对象和每个请求都是相同的。相当于在整个应用application中只实例化一次,常见的单例模式。

 

  参考文献:

    官方文档:asp.net core