日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

跟我一起学.NetCore之依赖注入作用域和对象释放

發(fā)布時(shí)間:2023/12/4 asp.net 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 跟我一起学.NetCore之依赖注入作用域和对象释放 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

????上一小節(jié)簡(jiǎn)單闡述了依賴注入及Asp.NetCore中自帶依賴注入組件的常規(guī)用法,其中提到容器管控了自己創(chuàng)建對(duì)象的生命周期,包含了三種生命周期:Singleton、Scoped、Transient,?對(duì)于Singleton、Transient相對(duì)于Scoped來(lái)說(shuō)比較好理解,其實(shí)這里面有一個(gè)作用域的概念,也可以理解為根容器和子容器的范圍;上一小節(jié)中有一個(gè)例子中說(shuō)到,當(dāng)注入的生命周期為Scoped的時(shí),在同一個(gè)請(qǐng)求內(nèi),注入的對(duì)象都是同一個(gè),這里Asp.NetCore將每個(gè)請(qǐng)求作為了一個(gè)作用域,在此作用域內(nèi),生命周期為Scoped的對(duì)象就是同一個(gè);下面簡(jiǎn)單說(shuō)說(shuō)作用域和對(duì)象釋放的常規(guī)知識(shí)點(diǎn);

正文

????作用域這里可以理解為服務(wù)范圍,由IServiceScope承載,如其源代碼所示,每一個(gè)服務(wù)范圍內(nèi)都一個(gè)根容器,如下所示:

//// 摘要:// /// The System.IDisposable.Dispose method ends the scope lifetime. Once Dispose// /// is called, any scoped services that have been resolved from /// Microsoft.Extensions.DependencyInjection.IServiceScope.ServiceProvider// will be /// disposed. ///public interface IServiceScope : Object, IDisposable{//?IServiceProvider?即代表容器//// 摘要:// /// The System.IServiceProvider used to resolve dependencies from the scope.// ///IServiceProvider ServiceProvider{get;}}

????每一個(gè)服務(wù)范圍內(nèi)可以通過(guò)自身IServiceProvider創(chuàng)建對(duì)應(yīng)的子作用域,而任何一個(gè)子作用域的IServiceProvider都有對(duì)根容器的引用,如下圖結(jié)構(gòu):

? ? 每一個(gè)IServiceProvider中都會(huì)將其創(chuàng)建的對(duì)象存入列表中,針對(duì)于繼承與IDisposable接口的類型對(duì)象會(huì)單獨(dú)存放在一個(gè)列表中,當(dāng)作用域IServiceScope對(duì)象的Dispose方法被調(diào)用時(shí),最終對(duì)應(yīng)IServicePorvider對(duì)應(yīng)的對(duì)象列表也會(huì)清空,針對(duì)于繼承與IDisposable類型的對(duì)象會(huì)調(diào)用其Dispose方法;最后導(dǎo)致對(duì)應(yīng)作用域下容器創(chuàng)建的對(duì)象成為垃圾對(duì)象,被GC給回收;

????在Asp.NetCore中,框架默認(rèn)將其分有根作用域(與引用程序同生命周期)和請(qǐng)求作用域(每一個(gè)請(qǐng)求一個(gè)作用域),通常也會(huì)稱其為根容器和請(qǐng)求容器,名稱分別為ApplicationServices和RequestServices,在程序中獲取方式如下:

  • ????通過(guò)IApplicationBuilder對(duì)象可以獲取ApplicationServices

  • ????通過(guò)HttpContext.RequestServices獲取RequestServices

????作用域簡(jiǎn)單舉例,在請(qǐng)求作用域下再創(chuàng)建子作用域,分別查看對(duì)應(yīng)不同生命周期對(duì)象是否一致,新建一個(gè)WebApi項(xiàng)目,針對(duì)三個(gè)生命周期添加了對(duì)應(yīng)文件,結(jié)構(gòu)如下:

????

對(duì)應(yīng)紅框內(nèi)的文件內(nèi)容如下:

???????細(xì)心的小伙伴可能會(huì)看到,每個(gè)實(shí)現(xiàn)類里面都繼承了IDisposable接口,這主要是后面顯示釋放用的,這里先不管;編輯好以上內(nèi)容之后就將其進(jìn)行注冊(cè),如下:

????接下來(lái)就是使用了,這里通過(guò)這Action中使用,在當(dāng)前的請(qǐng)求作用域下創(chuàng)建子作用域,對(duì)比每一個(gè)生命周期對(duì)象,如代碼所示:

[HttpGet] public string Get([FromServices]ITestSingleton testSingleton, [FromServices]ITestSingleton testSingleton1,[FromServices]ITestScoped testScoped, [FromServices]ITestScoped testScoped1,[FromServices]ITestTransient testTransient, [FromServices]ITestTransient testTransient1) {//獲取請(qǐng)求作用域(請(qǐng)求容器)var requestServices = HttpContext.RequestServices;//在請(qǐng)求作用域下創(chuàng)建子作用域using(IServiceScope scope = requestServices.CreateScope()){//在子作用域中通過(guò)其容器獲取注入的不同生命周期對(duì)象ITestSingleton testSingleton11 = scope.ServiceProvider.GetService<ITestSingleton>();ITestScoped testScoped11 = scope.ServiceProvider.GetService<ITestScoped>();ITestTransient testTransient11 = scope.ServiceProvider.GetService<ITestTransient>();ITestSingleton testSingleton12 = scope.ServiceProvider.GetService<ITestSingleton>();ITestScoped testScoped12 = scope.ServiceProvider.GetService<ITestScoped>();ITestTransient testTransient12 = scope.ServiceProvider.GetService<ITestTransient>();Console.WriteLine("================Singleton=============");Console.WriteLine($"請(qǐng)求作用域的ITestSingleton對(duì)象:{testSingleton.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域的ITestSingleton1對(duì)象:{testSingleton1.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域下子作用域的ITestSingleton11對(duì)象:{testSingleton11.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域下子作用域的ITestSingleton12對(duì)象:{testSingleton12.GetHashCode()}");Console.WriteLine("================Scoped=============");Console.WriteLine($"請(qǐng)求作用域的ITestScoped對(duì)象:{testScoped.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域的ITestScoped1對(duì)象:{testScoped1.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域下子作用域的ITestScoped11對(duì)象:{testScoped11.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域下子作用域的ITestScoped12對(duì)象:{testScoped12.GetHashCode()}");Console.WriteLine("================Transient=============");Console.WriteLine($"請(qǐng)求作用域的ITestTransient對(duì)象:{testTransient.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域的ITestTransient1對(duì)象:{testTransient1.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域下子作用域的ITestTransient11對(duì)象:{testTransient11.GetHashCode()}");Console.WriteLine($"請(qǐng)求作用域下子作用域的ITestTransient12對(duì)象:{testTransient12.GetHashCode()}");}return "TestServiceScope";}

????運(yùn)行,進(jìn)行請(qǐng)求,看打印結(jié)果:

????

  • ????對(duì)于Singleton來(lái)說(shuō)始終不變,因?yàn)槠涫歉S根容器生命周期,引用程序退出才釋放;

  • ????對(duì)于Scoped來(lái)說(shuō)只要在自己的作用域內(nèi)就是單例的;

  • ????對(duì)于Transient來(lái)說(shuō)始終創(chuàng)建;

????以上一直在說(shuō)釋放,下面利用繼承IDisposable接口釋放時(shí)會(huì)調(diào)用對(duì)應(yīng)Dispoable方法的原理簡(jiǎn)單演示各個(gè)生命周期的釋放時(shí)機(jī);在Controller中增加幾個(gè)Action方法,如下:

????這里使用IHostApplicationLifetime中的StopApplication模擬關(guān)閉程序釋放單例下的對(duì)象;運(yùn)行看效果:

? ??使用坑:不要從根容器中獲取Transient生命周期的對(duì)象,因?yàn)橥ㄟ^(guò)根容器創(chuàng)建的對(duì)象不會(huì)回收,除非等到應(yīng)用程序退出,這樣會(huì)導(dǎo)致內(nèi)存泄露;如下演示:

????

新增Action方法:

運(yùn)行,發(fā)送請(qǐng)求看結(jié)果:

總結(jié)

????作用域及對(duì)象釋放就簡(jiǎn)單說(shuō)這么多,容器只管理自己創(chuàng)建出來(lái)的對(duì)象生命周期;下一節(jié)說(shuō)說(shuō)使用第三方組件擴(kuò)展依賴注入功能;

總結(jié)

以上是生活随笔為你收集整理的跟我一起学.NetCore之依赖注入作用域和对象释放的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。