當乙個要生存很短時間的元件被乙個長期存在的元件持有時,就會發生「captive dependency」。 mark seemann的這篇部落格文章在解釋這個概念方面做得很好。
autofac不一定會阻止你建立捕獲依賴關係。由於捕獲的設定方式,您可能會發現解決方案異常的時候,但您並不總是如此。停止捕獲依賴是開發者的責任。
避免捕獲依賴的一般規則:
消費元件的生命週期應該小於或等於所消費的服務的生命週期。
基本上,不要讓乙個單例執行乙個例項每請求的依賴關係,因為它會被保留太久。
假設您有乙個web應用程式,它使用來自入站請求的一些資訊來確定連線的正確資料庫。您可能有以下元件:
接收當前請求和資料庫連線工廠的repository。
當前請求像乙個httpcontext,可以用來幫助決定業務邏輯。
資料庫連線工廠採用某種引數並返回正確的資料庫連線。
在這個例子中,考慮一下你想要為每個元件使用的生命週期範圍。當前的請求上下文是乙個明顯的 - 你想每個請求的例項。那其他的呢?
對於repository
,假設你選擇「singleton」。乙個單例建立一次,並為應用程式的生命週期進行快取。如果選擇「singleton」,那麼即使在當前請求結束之後,請求上下文也將被傳入並儲存在應用程式的整個生命週期中。該repository是長期存在的,但可以保持較短的壽命元件。這是乙個捕獲依賴。
但是,假設您將儲存庫設定為「每個請求的例項」(instance-per-request) - 現在只要當前請求存在且不再存在。這與它所需的請求上下文一樣長,所以現在它不是乙個捕獲。資源庫和請求上下文將同時發布(在請求結束時),一切都會好起來的。
更進一步說,你使repository「每個依賴的例項」,所以你每次都得到乙個新的。這還是可以的,因為它意圖比現在的要求更短的時間。它不會太長時間,所以沒有捕獲。
資料庫連線工廠經歷了類似的思考過程,但可能有一些不同的考慮因素。例項化工廠可能很昂貴,或者需要維護一些內部狀態才能正常工作。您可能不希望它是「每個請求的例項」或「每個依賴的例項」。您可能實際上需要它是乙個單例。
對於壽命較短的依賴關係,可以採用較長壽命的依賴關係。如果您的repository是「每個請求的例項」或「每個依賴的例項」,那麼您仍然會很好。資料庫連線工廠有意壽命更長。
這是乙個單元測試,它顯示了它強制建立乙個捕獲依賴的樣子。在這個例子中,使用「規則管理器」來處理通過應用程式使用的一組「規則」。
public
class rulemanager
public ienumerablerules
}public
inte***ce irule
public
class singletonrule : irule
public
class instanceperdependencyrule : irule
[fact]
public
void
captivedependency()
}
請注意,上面的示例並不直接顯示,但如果您要在container.beginlifetimescope()
呼叫中動態新增規則的註冊,則這些動態註冊將不會包含在已解析的rulemanager
中。rulemanager
是乙個單例,從動態新增的註冊不存在的根容器中解析出來。
另乙個**示例顯示如何建立乙個錯誤地繫結到子生命週期作用域的捕獲依賴關係時可能會發生異常。
public
class rulemanager
public ienumerablerules
}public
inte***ce irule
public
class singletonrule : irule
}public
class instanceperrequestdependency
[fact]
public
void
captivedependency()
}
鑑於應用程式的開發人員最終負責確定捕獲是否正常,開發人員可以確定單例可以接受,例如,採取「依賴每個例項的」服務。
例如,也許你有乙個快取類被故意設定為快取消費元件的生命週期的東西。 如果消費者是單例,則可以使用快取來儲存整個應用程式生命週期中的事物; 如果消費者是「每個請求的例項」,那麼它只儲存單個web請求的資料。 在這樣的情況下,最終可能會有乙個壽命較長的元件故意地依賴於乙個壽命較短的元件。
只要應用程式開發人員了解設定這些生命週期的後果,這是可以接受的。 也就是說,如果你打算這麼做的話,那就有意而非無意地去做。
Autofac官方文件 一 開始
將autofac整合到您的應用程式的基本模式是 記住控制反轉 ioc 的結構。新增autofac引用。在應用程式啟動.建立乙個containerbuilder。註冊元件。構建容器並將其儲存以備後用。在執行應用程式時 從容器建立乙個生命週期範圍。使用生命週期作用域來解析元件的例項。本入門指南將引導您完...
autofac文件 事件
開始 registering components 控制範圍和生命週期 用模組結構化autofac xml配置 與.net整合 深入理解autofac 指導關於 詞彙表在component生命週期的不同階段使用事件。autofac暴露三個事件介面供例項的不同階段呼叫 這些事件會在註冊的時候被訂閱,或...
autofac文件 關係型別
開始 registering components 控制範圍和生命週期 用模組結構化autofac xml配置 與.net整合 深入理解autofac 指導關於 詞彙表autofac提供拆箱即用的關係型別。autofac會對下面列出的關係型別特別解釋。下面列出的每一種關係型別,autofac都會在需...