談一談autofac組件的實(shí)例范圍
實(shí)例范圍決定如何在請求之間共享服務(wù)。
原文地址:http://docs.autofac.org/en/latest/lifetime/instance-scope.html
每個(gè)依賴一個(gè)實(shí)例
使用這個(gè)選項(xiàng),每次請求服務(wù)都會(huì)返回一個(gè)新實(shí)例。使用 InstancePerDependency() 指定。這是默認(rèn)選項(xiàng)。下面的代碼,第2行和第3行是等價(jià)的。
var builder = new ContainerBuilder(); builder.RegisterType<Worker>(); builder.RegisterType<Worker>().InstancePerDependency();
下面的代碼,每次循環(huán)都生成一個(gè)新的實(shí)例,一共生成 100 個(gè)實(shí)例。
using(var scope = container.BeginLifetimeScope()) { for(var i = 0; i < 100; i++) { var w = scope.Resolve<Worker>(); w.DoWork(); } }
單個(gè)實(shí)例
使用這個(gè)選項(xiàng),在根范圍或嵌套范圍中請求服務(wù),都返回同一個(gè)的實(shí)例。使用 SingleInstance() 指定。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().SingleInstance();
下面的代碼,w1 和 w2 始終是同一個(gè)對(duì)象,100 次循環(huán)只有一個(gè) Worker 類的實(shí)例。
using(var scope1 = container.BeginLifetimeScope()) { for(var i = 0; i < 100; i++) { var w1 = scope1.Resolve<Worker>(); using(var scope2 = scope1.BeginLifetimeScope()) { var w2 = scope2.Resolve<Worker>(); } } }
每個(gè)生命周期范圍一個(gè)實(shí)例
使用這個(gè)選項(xiàng),在特定的 ILifetimeScope 中請求服務(wù),只返回一個(gè)實(shí)例。使用 InstancePerLifetimeScope() 指定。下面的代碼中,scope1 中的 100 次 w1 是同一個(gè)對(duì)象,scope2 中的 100 次 w2 是同一個(gè)對(duì)象,但是 w1 和 w2 不是同一個(gè)對(duì)象。
var builder = new ContainerBuilder(); builder.RegisterType<Worker>().InstancePerLifetimeScope(); using(var scope1 = container.BeginLifetimeScope()) { for(var i = 0; i < 100; i++) { var w1 = scope1.Resolve<Worker>(); } } using(var scope2 = container.BeginLifetimeScope()) { for(var i = 0; i < 100; i++) { var w2 = scope2.Resolve<Worker>(); } }
每個(gè)匹配的生命周期范圍一個(gè)實(shí)例
類似于上面【每個(gè)生命周期范圍一個(gè)實(shí)例】,但可以提供更多控制。使用此選項(xiàng),允許為 ILifetimeScope 對(duì)象提供“標(biāo)記”。在標(biāo)記匹配的范圍中只有一個(gè)實(shí)例。使用 InstancePerMatchingLifetimeScope() 方法指定。
var builder = new ContainerBuilder(); builder.RegisterType<Worker>().InstancePerMatchingLifetimeScope("x");
下面的代碼中,w1 和 w2 相同,w3 和 w4 相同,但 w1 和 w3 不同。
using(var scope1 = container.BeginLifetimeScope("x")) { for(var i = 0; i < 100; i++) { var w1 = scope1.Resolve<Worker>(); using(var scope2 = scope1.BeginLifetimeScope()) { var w2 = scope2.Resolve<Worker>(); } } } using(var scope3 = container.BeginLifetimeScope("x")) { for(var i = 0; i < 100; i++) { var w3 = scope3.Resolve<Worker>(); using(var scope4 = scope1.BeginLifetimeScope()) { var w4 = scope4.Resolve<Worker>(); } } }
解析時(shí)必須提供提供合適的標(biāo)記,以下代碼會(huì)拋出異常。
using(var noTagScope = container.BeginLifetimeScope()) { var fail = noTagScope.Resolve<Worker>(); }
每個(gè)請求一個(gè)實(shí)例
有些應(yīng)用程序天然具有【請求】語義,例如 ASP.NET MVC 或 WebForm 應(yīng)用程序。【每個(gè)請求一個(gè)實(shí)例】在【每個(gè)匹配的生命周期范圍一個(gè)實(shí)例】基礎(chǔ)上,通過提供范圍標(biāo)記,注冊函數(shù)和常見類型集成實(shí)現(xiàn)。本質(zhì)上是【每個(gè)匹配的生命周期范圍一個(gè)實(shí)例】。
var builder = new ContainerBuilder(); builder.RegisterType<Worker>().InstancePerRequest();
ASP.NET Core 使用【每個(gè)生命周期范圍一個(gè)實(shí)例】,而不是【每個(gè)請求一個(gè)實(shí)例】。
每個(gè)Owned 一個(gè)實(shí)例
Owned<T> 隱式關(guān)聯(lián)類型創(chuàng)建嵌套的生命周期范圍。使用 instance-per-owned 注冊,可將依賴限定在 owned 實(shí)例中。
var builder = new ContainerBuilder(); builder.RegisterType<MessageHandler>(); builder.RegisterType<ServiceForHandler>().InstancePerOwned<MessageHandler>();
本例中 ServiceForHandler 服務(wù)會(huì)限制在 MessageHandler 實(shí)例范圍內(nèi)。
using(var scope = container.BeginLifetimeScope()) { // MessageHandler 和附屬的 ServiceForHandler // 在 scope 下面的一個(gè)微型的 lifetime scope 中。 // 解析 Owned<T> 需要程序員負(fù)責(zé)執(zhí)行清理工作。 var h1 = scope.Resolve<Owned<MessageHandler>>(); h1.Dispose(); }
線程范圍
Autofac 可以強(qiáng)制使A線程的對(duì)象不滿足B線程的依賴。
var builder = new ContainerBuilder(); builder.RegisterType<MyThreadScopedComponent>() .InstancePerLifetimeScope(); var container = builder.Build();
然后讓每個(gè)創(chuàng)建自己的 lifetime scope
void ThreadStart() { using (var threadLifetime = container.BeginLifetimeScope()) { var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>(); } }
重要:在多線程場景下,要小心不要將父范圍清理掉。否則,派生線程中的子范圍將無法解析服務(wù)。
每個(gè)線程都將有自己的 MyThreadScopedComponent 實(shí)例,本質(zhì)上是生命周期范圍內(nèi)的單例。范圍內(nèi)的實(shí)例不會(huì)提供到外部,因此很容易保持線程間的組件隔離。
通過添加 ILifetimeScope 參數(shù),可將父范圍注入到生成線程的代碼中,Autofac 會(huì)將當(dāng)前范圍自動(dòng)注入,接下來可以使用它創(chuàng)建嵌套范圍。
public class ThreadCreator { private ILifetimeScope _parentScope; public ThreadCreator(ILifetimeScope parentScope) { this._parentScope = parentScope; } public void ThreadStart() { using (var threadLifetime = this._parentScope.BeginLifetimeScope()) { var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>(); } } }
如果想進(jìn)一步控制,可以使用【每個(gè)匹配的生命周期范圍一個(gè)實(shí)例】將線程范圍的組件同內(nèi)部生命周期范圍關(guān)聯(lián)起來,這個(gè)方式的效果如圖:
圖中的"Context"是 BeginLifetimeScope 方法創(chuàng)建的生命周期范圍。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:C#獲取HTML文本的第一張圖片與截取內(nèi)容摘要示例代碼
欄 目:C#教程
本文標(biāo)題:談一談autofac組件的實(shí)例范圍
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6206.html
您可能感興趣的文章
- 01-10雜談try-catch-finally異常處理
- 01-10再談異常處理try catch finally
- 01-10淺談C#中簡單的異常引發(fā)與處理操作
- 01-10淺談C#指針問題
- 01-10談?wù)凜# replace在正則表達(dá)式中的意義
- 01-10淺談Visual C#進(jìn)行圖像處理(讀取、保存以及對(duì)像素的訪問)
- 01-10談C# using的用法與好處
- 01-10淺談C#中的值類型和引用類型
- 01-10淺談C# 非模式窗體show()和模式窗體showdialog()的區(qū)別
- 01-10淺談C#各種數(shù)組直接的數(shù)據(jù)復(fù)制/轉(zhuǎn)換


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻 器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁面的局部加載