淺談.net core 注入中的三種模式:Singleton、Scoped 和 Transient
從上篇內(nèi)容不如題的文章《.net core 并發(fā)下的線程安全問題》擴(kuò)展認(rèn)識.net core注入中的三種模式:Singleton、Scoped 和 Transient
我們都知道在 Startup 的ConfigureServices 可以注入我們想要的服務(wù),那么在注入的時候有三種模式可以選擇,那么我們在什么時候選擇什么樣的模式呢?
在講注入模式之前,我覺得很有必要了解服務(wù)生存期的概念!
服務(wù)生存期:ASP.NET Core 提供了一個內(nèi)置的服務(wù)容器 IServiceProvider負(fù)責(zé)管理服務(wù)的生命周期,從被依賴注入容器創(chuàng)建開始(就是將服務(wù)注入到你要使用的類的構(gòu)造函數(shù)中),然后框架負(fù)責(zé)創(chuàng)建依賴關(guān)系的實(shí)例,并在不再需要時對其進(jìn)行處理(就是說等我們調(diào)用完服務(wù)時,容器會自己去對注入的服務(wù)進(jìn)行釋放)。
IServiceProvider 怎么負(fù)責(zé)的呢?
// System.IServiceProvider using System; public interface IServiceProvider { object GetService(Type serviceType); }
可以看出是通過 GetService此接口的方法獲取提供服務(wù)的對象。那再走深一點(diǎn)找找,我們看看程序集 Microsoft.Extensions.DependencyInjection 是怎么提供這個容器的
//Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder> using Microsoft.Extensions.DependencyInjection; using System; public interface IServiceProviderFactory<TContainerBuilder> { TContainerBuilder CreateBuilder(IServiceCollection services); IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder); }
看到上面的IServiceProviderFactory 接口是不是很熟悉了,這個容器里會有一個 IServiceCollection(服務(wù)集合),那服務(wù)怎么加進(jìn)入(實(shí)現(xiàn))的呢
//Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions using System; private static IServiceCollection Add(IServiceCollection collection, Type serviceType, Type implementationType, ServiceLifetime lifetime) { ServiceDescriptor item = new ServiceDescriptor(serviceType, implementationType, lifetime); collection.Add(item); return collection; }
到這里,已經(jīng)很清楚了,也已經(jīng)接近我們今天的主題了,直接來吧
// Microsoft.Extensions.DependencyInjection.ServiceLifetime public enum ServiceLifetime { Singleton, Scoped, Transient }
上面的枚舉里面就是提供了Singleton、Scoped 和 Transient 三種模式。去微軟的文檔里面看看,先了解一下這三種模式,在 ServiceCollectionServiceExtensions 就只有3個方法(有重載喲)
從源碼里面絕對可以想到,這3個方法是繼承 IServiceCollection。好了,說說這三種模式先,畢竟實(shí)現(xiàn)我們不是很關(guān)心(關(guān)心就看文檔看源碼)
(1)Singleton 單一實(shí)例模式:單一實(shí)例對象對每個對象和每個請求都是相同的,可以說是不同客戶端不同請求都是相同的。
(2)Transient 暫時性模式:暫時性對象始終不同,無論是不是同一個請求(同一個請求里的不同服務(wù))同一個客戶端,每次都是創(chuàng)建新的實(shí)例。
(3)Scoped作用域模式:作用域?qū)ο笤谝粋€客戶端請求中是相同的,但在多個客戶端請求中是不同的。(這句是文檔的原話,我覺得描述的很清晰)
什么時候用哪種模式?這個不大好說(希望這個可以成為討論點(diǎn))
比如一下吧:
1、日志記錄器可以實(shí)現(xiàn)為單例,因?yàn)樵谡麄€生命周期內(nèi)都可以只使用一個實(shí)例;
2、數(shù)據(jù)庫訪問上下文(DbContext)選擇 Scoped 的應(yīng)該是最佳候選,因?yàn)?services.AddDbContext 默認(rèn)就是 Scoped(哈哈哈);
3、如果需要利用深度依賴關(guān)系圖(a deep dependency graph)創(chuàng)建惟一對象,則可以考慮將該對象注冊為 transient 。
還有看看別人怎么說(對Scoped的描述,在理解上可能不大一樣,見仁見智了老鐵)
還有一個stackoverflow 的
按別人的經(jīng)驗(yàn),可以作為參考參考:
怎么驗(yàn)證?請用 官方例子 運(yùn)行一下看結(jié)果:
瀏覽器第一個tab頁面(第一個請求,可以認(rèn)為是一個客戶端):
瀏覽器第二個tab頁面(第二個請求,可以認(rèn)為是另一個客戶端):
看上面的結(jié)果就不多說了。
這篇擴(kuò)展認(rèn)識寫得還蠻有意思的,尤其是在找這三種模式的使用場景,雖然自己有點(diǎn)見解,但絕對不完整。如更好的見解,很希望能一起分享一下。
下一篇的擴(kuò)展好像要回到源頭,擼擼 .net core 的注入了,哈哈哈……
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ASP.NET Core應(yīng)用錯誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開發(fā)者
這篇文章主要給大家介紹了關(guān)于ASP.NET Core應(yīng)用錯誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開發(fā)者異常頁面”的相關(guān)資料,需要的朋友可以參考下2019-01-01asp.net 計劃任務(wù)管理程序?qū)崿F(xiàn),多線程任務(wù)加載
b/s模式下用程序?qū)崿F(xiàn)計劃任務(wù),一直是個不太好解決和管理的問題,當(dāng)然可以采用ajax 計時器的方法模擬form端的timer事件。2009-11-11ASP.NET三層架構(gòu)詳解 如何實(shí)現(xiàn)三層架構(gòu)
這篇文章主要為大家詳細(xì)介紹了ASP.NET三層架構(gòu),如何實(shí)現(xiàn)三層架構(gòu),本文為大家揭曉,感興趣的小伙伴們可以參考一下2016-05-05.NET Core 處理 WebAPI JSON 返回?zé)┤说膎ull為空
這篇文章主要介紹了.NET Core 處理 WebAPI JSON 返回?zé)┤说膎ull為空,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01SqlCommandBuilder類批量更新excel或者CSV數(shù)據(jù)的方法
這篇文章主要介紹了SqlCommandBuilder類批量更新excel或者CSV數(shù)據(jù)的方法,需要的朋友可以參考下2015-10-10asp.net對URL含有中文參數(shù)的轉(zhuǎn)換
asp.net的傳參中經(jīng)常使用到中文參數(shù)的處理,下面的函數(shù)可以解決中文參數(shù)的問題2008-03-03