asp.net core 3.1学习笔记——作用域与对象的释放行为

一、原理和注意事项:

作用域由 IServiceScope 对象承载,对于实现了IDisposable接口类型的对象,容器会去负责对其生命周期的管理,当使用完毕它会去释放对象;实现IDisposable接口类型对象的释放特点:

  • DI 只负责释放由其创建的对象;
  • DI 在容器或子容器释放时,释放由其创建的对象实例;

如果对象是由我们自己创建并放到容器里面,容器不负责释放该对象;容器的生命周期与其创建的对象的生命周期有对应关系,这里我们需要以下两点注意事项:

  • 在根容器不要去创建实现了 IDisposable 的瞬时服务;
  • 避免手动创建对象且将该对象放入容器里面,应该尽可能的使用容器去管理我们的对象的创建和释放;

二、代码示例与测试结果:

首先创建一个 OrderService 的服务,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace DependencyInjectionScopeAndDisposableDemo.Services
{
    public interface IOrderService
    {

    }

    public class DisposableOrderService : IOrderService, IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine($"DisposableOrderService Disposed:{this.GetHashCode()}");
        }
    }
}

然后在 Startup 的 ConfigureServices 中分别注册以下服务,测试作用域对象的生命周期和释放,如下所示:

//1.瞬态
services.AddTransient<IOrderService, DisposableOrderService>();
services.AddTransient<IOrderService>(service => new DisposableOrderService()); //工厂模式注册;

//2.单例
services.AddSingleton<IOrderService, DisposableOrderService>();
services.AddSingleton<IOrderService>(services => new DisposableOrderService());

//3.作用域
services.AddScoped<IOrderService, DisposableOrderService>();
services.AddScoped<IOrderService>(services => new DisposableOrderService());

//4.自创建方式单例注册
var service = new DisposableOrderService();
services.AddSingleton<IOrderService>(service);

测试输出对象的HashCode和该对象的生命周期和释放行为,控制器方法如下:

  • 瞬态服务注册测试:
[HttpGet]
public int Get(
    [FromServices]IOrderService orderService,
    [FromServices]IOrderService orderService2) 
{
    Console.WriteLine("接口请求处理结束");
    return 1;
}

1.瞬态测试输出结果如下:

接口请求处理结束
DisposableOrderService Disposed:21621962
DisposableOrderService Disposed:29422698

瞬时服务在每一接口调用时都会获得一个对象,且在接口处理完毕后将其注册对象服务释放;
  • 单例服务注册测试:
2.单例测试,控制器中的请求方法不变(如下3),测试结果如下:

=======1==========
=======2==========
接口请求处理结束

执行顺序一样,但单例模式注册服务的对象不会被释放;
  • 作用域服务注册测试:
[HttpGet]
public int Get(
    [FromServices]IOrderService orderService,
    [FromServices]IOrderService orderService2) 
{
    #region 测试作用域Scope
    Console.WriteLine("=======1==========");
    using (IServiceScope scope = HttpContext.RequestServices.CreateScope())
    {
        //创建作用域子容器
        var service = scope.ServiceProvider.GetService<IOrderService>();
        var service2 = scope.ServiceProvider.GetService<IOrderService>();
    }
    Console.WriteLine("=======2==========");
    #endregion

    Console.WriteLine("接口请求处理结束");
    return 1;
}

3.作用域测试输出结果如下:

=======1==========
DisposableOrderService Disposed:8140213
=======2==========
接口请求处理结束
DisposableOrderService Disposed:21353980

同样作用域服务注册还是先执行接口方法,执行完毕再将其对象释放,但同一个作用域内对象只会创建一次(局部单例模式);
  • 自创建方式单例注册
4.测试结果如下:

=======1==========
=======2==========
接口请求处理结束

同样的测试结果,自创建注册方式,对象不会被其容器所释放;

以上就是对服务注册的几种方式以及对象释放的生命周期测试结果;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章