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