手把手教你写DI_3_小白徒手支持 Singleton 和 Scoped 生命周期
在上一節:手把手教你寫DI_2_小白徒手擼構造函數注入
渾身繃帶的小白同學:我們繼續開展我們的工作,大家都知道?Singleton是什么,就是全局只有一個唄,我們就先從它開始,這個多簡單,我們找個字典放這些對象就ok啦
大神:我的刀呢?
小白同學:我錯啦!!!
小白同學:好了,我們來說下?Scoped?作用域,百度百科的解釋是這樣的: 作用域(scope),程序設計概念,通常來說,一段程序代碼中所用到的名字并不總是有效/可用的,而限定這個名字的可用性的代碼范圍就是這個名字的作用域。
作用域的使用提高了程序邏輯的局部性,增強程序的可靠性,減少名字沖突。
對于對象而言(其他也是一樣的),在main函數中,對象的作用域為他所在的最近的一對花括號內。在后花括號處析構函數被調用;全局的對象的作用域為聲明之后的整個文件,析構函數在最后被調用。另外,臨時產生的對象在使用完后立即會被析構。
小白同學:雖然比較奇怪為啥百度百科強調的是名字,名字不過是我們方便自己對應以及找到變量/內存地址等的手段而已。不過不管啦,反正DI里面的Scoped概念和這段解釋有點點相似,是為DI提供將對象生命周期控制在自定義的范圍內部的一個手段,比如我們保證http 一次請求的生命周期內,一些比如context之類的處理,我們就可以用這樣的作用域概念處理,
小白同學:作用域由于考慮到不是我們自己控制,這是有使用者自定的,所以我們需要提供一些抽象接口讓用戶可以使用。這里呢,我們就偷懶啦,抄襲一下別人的定義
小白同學:大家看,多簡單,完美
大神:你問過我的青龍偃月刀了嗎?
小白同學(尷尬): 哈哈,怎么可能寫完了,我是開個玩笑,肯定要把服務定義給過去
青龍偃月刀:你希望你的生命周期也和這個ServiceScopeFactory一樣無處安放嗎?
小白同學:為啥?我這不是實現了嗎?
青龍偃月刀:ServiceScopeFactory?用戶從哪里拿?
小白同學:我放進ServiceDefintions呀,
var a = new ServiceDefintions(); a.Add(new DelegateServiceDefintion(typeof(IServiceScopeFactory),typeof(ServiceScopeFactory),Lifetime.Transient, i => new ServiceScopeFactory(a)));青龍偃月刀:hehe,?ServiceProvider?由?IServiceScopeFactory?創建的都是新的吧?
小白同學:對,就是這樣,才能保證是新的作用域呀
青龍偃月刀:hehe, 那新的?ServiceProvider?創建的對象也是新的吧?
小白同學:對,就是這樣,新的作用域創建的對象肯定和舊的作用域創建的對象肯定不一樣
青龍偃月刀:hehe, 那Singleton不是全局唯一嗎?
小白同學:啥?Singleton和作用域有什么關系?我不是有字典緩存了嗎?
青龍偃月刀:我真恨不得自己再把自己磨快點。
青龍偃月刀:ServiceProvider?是不是可以創建 三種不同生命周期的對象?
小白同學:對,Singleton?,Scoped,?Transient
青龍偃月刀:那新的ServiceProvider創建的Singleton對象呢?
小白同學:都是從緩存字典private readonly ConcurrentDictionary<Type, object> singletonCache?里面拿唄
青龍偃月刀:。。。。。。 這個字典你放哪呢?
小白同學:我放ServiceProvider類上啊
青龍偃月刀:。。。。。。 那每一個新的ServiceProvider是不是都有一個新的緩存字典?
小白同學:吃驚.gif, 不愧是寶刀
小白同學:我換靜態的?static ConcurrentDictionary<Type, object> singletonCache
青龍偃月刀:那整個程序就只有一份了啊
小白同學:對呀,就是只要一份
青龍偃月刀:那一個程序里面多個DI容器呢?
小白同學:大吃一驚.gif,還能這么玩?
青龍偃月刀:不說其他,就說你單元測試一個DI容器能測試各種場景?
小白同學:尷尬.gif 我目前只寫了一個
青龍偃月刀:...............你改吧
小白同學:哦
小白同學:我們就可以這樣注冊ServiceScopeFactory了
var a = new ServiceDefintions(); a.Add(new DelegateServiceDefintion(typeof(IServiceScopeFactory),typeof(ServiceScopeFactory),Lifetime.Transient, i => new ServiceScopeFactory(i)));青龍偃月刀:磨刀石呢?我要磨快點
小白同學:又咋了,我寫的這么完美?
青龍偃月刀:你確定這樣符合作用域的概念?
小白同學:怎么不符合了?SingletonCache?都只有一個了,每個ServiceProvider都是創建新的Scoped生命周期對象
青龍偃月刀:你看看你是怎么寫創建新的Scoped生命周期對象的?
小白同學:這樣啊
? ? ? ?case Lifetime.Scoped: ? ? ? ? ? ? return CreateObj(x);青龍偃月刀:一個Scoped生命周期內,一個ServiceType對應生成對象不該唯一嗎?
小白同學:為啥啊?生命周期不是用戶自己控制了嗎?
青龍偃月刀:一個方法的作用域內,可以聲明多個同名對象嗎?
小白同學:不能呀
青龍偃月刀:那你允許一個Scoped作用域內,可以生成相同ServiceType,實際不同的對象?
小白同學:他可以自己回收唄
青龍偃月刀:你讓人家自己回收 !!!??? 那人家為什么不用Transient,你這樣和Transient有什么區別?
小白同學:你說的好有道理,我竟無言以對
小白同學:那我加緩存
小白同學:怎么樣?完美吧?
青龍偃月刀:我勸你好好考慮一下,我的大刀已經饑渴難耐
小白同學:哪兒不完美?明明很beautiful
青龍偃月刀:再提示一下,用戶是不是會這樣用?
IServiceProvider a = IServiceScopeFactory.CreateScopeProvider();doSomethings(a);a.Dispose();小白同學:對呀,可以完美應對呀
青龍偃月刀:。。。。。。。。。你的Dispose做了什么?
小白同學:emmmm 什么。。。 都沒做?
青龍偃月刀:那用戶Dispose什么?
小白同學:emmmm。。。。。。
小白同學:好吧,既然有問題我們再改下
青龍偃月刀:........... 一個子作用域可以把SingletonCache?Dispose 了?難道活到98歲不好嗎?
小白同學:啊。。。。。活到那么久很好啊。。。。哈,我知道怎么改
小白同學:真完美!!!!!
青龍偃月刀:呵呵,這樣也能算完美?多少沒做,還有多少問題沒搞?你看人家做成這樣子都算差的了 -?https://github.com/fs7744/Norns
原文地址:?https://www.cnblogs.com/fs7744/p/9931141.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的手把手教你写DI_3_小白徒手支持 Singleton 和 Scoped 生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手把手教你写DI_0_DI是什么?
- 下一篇: 手把手教你写DI_2_小白徒手撸构造函数