• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

作用域主要由接口IServiceScope承载。

实现IDisposable接口类型的发布。

DI只负责释放它创建的对象实例。

当DI容器或子容器被释放时,由它创建的对象实例也被释放。

解释:

对于实现IDisposable类实例的对象,我们的容器将负责管理它们的生命周期,当我们用完这些对象时,它将释放它们,但有两点需要注意:

DI/container只对自己创建的对象负责:也就是说,如果我们的对象是自己创建并放入容器的,容器不负责释放这个对象。

当容器和子容器被释放时,容器将释放这些对象:也就是说,容器的生命周期与其创建的对象的生命周期相对应。

建议

避免获取在根容器中实现IDisposable接口的即时服务;

避免手动创建实现IDisposable的对象,并使用容器来管理它们的生命周期。

解释:

在这种情况下,我们需要注意两点:

第一个是:在根容器中,我们最好不要创建即时服务,实现IDisposable的即时服务;

第二是避免手动创建对象,然后将它们塞进容器。我们应该尽可能多地使用容器来管理对象的创建和释放。

瞬时Transient服务

公共接口IOrderService{}

公共类disposableorderservice : IOrderService,IDisposable{

public void Dispose(){

控制台。WriteLine($ ' disposeableorderservice disposed : { this。get hashcode()} ');

}

}

公共void configure services(IServiceCollection服务){

服务。AddTransientIOrderService,DisposableOrderService();

服务。add controllers();

}

[HttpGet]

public int get([from services]io order service order service,[from services]io order service order service E2){//get两次。

控制台。WriteLine(“接口请求处理结束”);

返回1;

}

两个对象在执行后被释放:

image

结果是两次释放输出,每次释放的对象hashcode都不一样,也就是说每次瞬时注册的服务得到的实例都不一样,整个请求结束后才会触发释放。

作用域Scoped服务(重点)

将上面的瞬时注册更改为作用域注册:

//服务。AddTransientIOrderService,DisposableOrderService();

服务。AddScopedIOrderService(p=new DisposableOrderService());

[HttpGet]

public int Get([from services]IOrderService orderService,[from services]IOrderService orderService 2){

控制台。WriteLine('========1=======');

//HttpContext。RequestServices表示当前请求的容器,是应用程序根容器的子容器,每个请求都会创建一个容器。

//我们在这个子容器下创建另一个子容器范围来获取我们的服务。

使用(iservicescope scope=HttpContext。request services . create scope()){//via httpcontext . request se

rvices 创建 Scoped var service = scope.ServiceProvider.GetService<IOrderService>(); //var service2 = scope.ServiceProvider.GetService<IOrderService>(); // 即使你加上这句,输出结果还是2条释放 } Console.WriteLine("========2========"); Console.WriteLine("接口请求处理结束"); return 1; }

image
每次请求都获取到两个释放,意味我们每创建一个Scope的作用域,每个作用域内我们可以是单例的;

单例Singleton服务

将上述的瞬时注册改为单例Singleton注册:

//services.AddTransient<IOrderService, DisposableOrderService>();
services.AddSingleton<IOrderService>(new  DisposableOrderService());
//services.AddScoped<IOrderService>(p => new  DisposableOrderService());
[HttpGet]
public int Get([FromServices]IOrderService orderService, [FromServices]IOrderService orderService2){
    Console.WriteLine("========1========");
    // HttpContext.RequestServices 表示当前请求的根容器,是应用程序根容器的一个子容器,每个请求都会创建一个容器
    // 我们在这个子容器下再创建一个子容器来获取我们的服务
    using(IServiceScope scope = HttpContext.RequestServices.CreateScope()){
        var service = scope.ServiceProvider.GetService<IOrderService>();
        var service2 = scope.ServiceProvider.GetService<IOrderService>();
    }
    Console.WriteLine("========2========");
    return 1;
}

image
发现单例模式是没有释放的;

当我们使用单例时,其服务的实例是我们自己创建的话:

var servi = new  DisposableOrderService();
services.AddSingleton<IOrderService>(servi);
[HttpGet]
public int Get([FromServices]IOrderService orderService, 
        [FromServices]IOrderService orderService2,
		[Fromservices]IHostApplicationLifetime hostApplicationLifetime,
		[FromQuery] stop){
    Console.WriteLine("========1========");
    // HttpContext.RequestServices 表示当前请求的根容器,是应用程序根容器的一个子容器,每个请求都会创建一个容器
    // 我们在这个子容器下再创建一个子容器来获取我们的服务
    using(IServiceScope scope = HttpContext.RequestServices.CreateScope()){
        var service = scope.ServiceProvider.GetService<IOrderService>();
        var service2 = scope.ServiceProvider.GetService<IOrderService>();
    }
    Console.WriteLine("========2========");
    if(stop) hostApplicationLifetime.StopApplication();   // 停止应用程序
    return 1;
}

上述代码运行时,当我们触发停止应用程序后,我们是不会得到任何释放的输出,因为其创建的实例不是由容器来完成的,容器自然也不会管理到其释放(不会去管理对象生命周期的);
image
但是改成如下后:

services.AddSingleton<IOrderService, DisposableOrderService>();

image
当我们触发停止应用程序后,我们得到了一个释放的输出;

当我们注册一个瞬时服务:

public void ConfigureService(IServiceCollection services){
    services.AddTransient<IOrderService, DisposableOrderService>();
}

同时,在 Configure 方法中 从根容器获取瞬时服务时:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){
    // 从根容器获取瞬时服务
    var s = app.ApplicatonServices.GetService<IOrderService>();
    ...
}

这意味着我们会在根容器去持续的创建我们的IOrderService,但是由于根容器只会在应用程序整个退出时回收,也就意味着我们的这些对象会直积累在我们的应用程序内;
上述代码运行后,只有在项目退出时才会释放回收;
即:我们实现了IDisposable接口的服务,如果是注册瞬时的,我们又在根容器去做操作,它会一直保持到我们的应用程序退出的时候才能够被回收掉,所以说我们瞬时的服务,如果我们是实现了IDisposable的接口,就不建议使用根容器来去创建我们的对象;

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now