![](/img/trans.png)
[英]How can I resolve a registered Dependency from an Autofac Container in .NET Core 3.1
[英]How can a dependency (registered in nested LifetimeScope) be resolved from autofac container
有什么方法可以解決容器的依賴關系(實際上是在嵌套的 LifetimeScope 中注冊的,而不是在容器中)?
實際執行說明:
我有包含當前用戶基本信息的ApplicationContext
類(在其構造函數中注入了IServiceProvider
)。 它首先從serviceProvider
解析IHttpContextAccessor
,然后從httpContextAccessor.HttpContext
提取用戶信息。 ApplicationContext
類被注入到所有存儲庫/服務中。
但是,在一些靜態類中,我從靜態 IoC 類(包裝在其中的 autofac 容器)解析ApplicationContext
類。 我認為這是唯一的解決方案,因為我無法注入靜態構造函數。
我正在實現事件總線,我EventBusContext
創建了EventBusContext
類,該類從事件數據接收用戶信息。
ApplicationContext
類嘗試從IServiceProvider
解析EventBusContext
並僅在它獲取HttpContext
為 null 時從中提取用戶信息(這意味着此執行不是從 Http Request 開始)。
一旦EventBus
類接收到來自 RabbitMQ 的事件,它就會創建EventBusConext
類,將用戶信息添加到其中並動態注冊到新創建的嵌套LifetimeScope
然后解析EventHandler
類並調用 Handle 方法(通過反射)。
一切正常! 僅當EventHandler
使用從靜態IoC
類解析ApplicationContext
類的任何類時才會出現此問題,因為靜態IoC
類在內部嘗試從 autofac 容器(包裝在其中)解析EventBusContext
但它未能這樣做。
我將專注於開始的最初問題:
有什么方法可以解決容器的依賴關系(實際上是在嵌套的 LifetimeScope 中注冊的,而不是在容器中)?
最簡潔的答案是不。 如果在子作用域中注冊/添加了某些內容,則父作用域無法知道它。
Autofac 范圍是分層的。有很多關於此的文檔,包括一個圖表來說明這一點。
試圖將其歸結為“規則”,我們可以說:
這非常簡化,但足以說明這一點。
如果您將內容動態添加到子生命周期范圍內,您將只能在該子生命周期范圍以及您從那里創建的任何子范圍內訪問它們。
var builder = new ContainerBuilder();
builder.RegisterType<A>();
var container = builder.Build();
// This will work (though it's recommended you avoid resolving things
// from containers because it can lead to memory leaks).
// https://autofac.readthedocs.io/en/latest/lifetime/index.html
container.Resolve<A>();
// This will NOT work. The container doesn't have B in it.
container.Resolve<B>();
using(var scope1 = container.BeginLifetimeScope(b => b.RegisterType<B>())
{
// This will work. The child scope knows about parent registrations.
scope1.Resolve<A>();
// This will also work. The registration was added to the scope.
scope1.Resolve<B>();
// This will STILL NOT WORK. The parent does NOT know about child scopes.
container.Resolve<B>();
using(var scope2 = scope1.BeginLifetimeScope())
{
// These will work. The child scope knows about parent registrations.
scope2.Resolve<A>();
scope2.Resolve<B>();
// This will STILL NOT WORK.
container.Resolve<B>();
}
}
沒有黑客或解決方法。 它是故意分層的。
如果您需要訪問請求級別的項目(或者需要動態注冊在子生命周期范圍內的事物),那么獲取它們的唯一方法是從該子生命周期范圍或嵌套子項中解析。
更具體的目標:
從實現描述中,您有一些東西故意在請求之外運行並從根容器解析(同樣,這不是一個好主意,但它就是這樣)。 如果這些東西突然需要通過請求即時注冊的項目,那么您基本上有兩種選擇,這兩種選擇都是“您需要更改架構/設計”。
實際上,提供一個完全更新的設計或“工作代碼”來說明這些事情中的任何一個,與其說是對問題的回答,不如說是一種咨詢工作。 然而不幸的是,獲取每個請求數據的解決方案意味着您需要更改您的設計。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.