[英]Autofac lifetime scope usage
我有一個.net微服務,該服務具有一個InstancePerLifetimeScope的服務A。 服務A被注入到MessageService(單個服務)中。
public class MessageService
{
private readonly ServiceA serviceA;
public MessageService(ServiceA serviceA)
{
this.serviceA = serviceA;
}
public void ProcessItem(ItemClass item)
{
serviceA.Proccess(item);
}
}
這樣,ServiceA就會被任何調用它的線程變成單例。 要實現InstancePerLifetimeScope,我需要:
public class MessageService
{
private readonly IContainer container;
public MessageService(IContainer container)
{
this.container = container;
}
public void ProcessItem(ItemClass item)
{
using (var scope = container.BeginLifetimeScope())
{
scope.Resolve<ServiceA>().Proccess(item);
}
}
}
這是好習慣嗎? 我讀到這是服務定位器模式,被認為是反模式。 將容器作為可注射容器直接傳遞到服務中也不是最好的方法。
public class ServiceAFactory
{
private readonly IContainer container;
public ServiceAFactory(IContainer container)
{
this.container = container;
}
public IServiceA swapsService CreateService()
{
using (var scope = container.BeginLifetimeScope())
{
return scope.Resolve<IServiceA>();
}
}
}
避免在應用程序代碼中使用容器,而應僅將其用作“ 合成根目錄”的一部分。 有很多方法可以做到這一點,因此沒有一個唯一的答案,但是通常您希望從業務代碼中提取與Container有關的代碼。
在您的簡單示例中,似乎所有類都與容器相關,因此這意味着將其完全移至“合成根”。 由於Composition Root應該依賴於其他所有內容 ,而應用程序代碼不應依賴於Composition Root,因此這意味着其他代碼無法調用MessageService
。 通過引入抽象,可以輕松優雅地解決此問題: IMessageService
:
public class MessageService : IMessageService
{
...
}
該接口應在應用程序級別定義,在“合成根”內部實施。
如果MessageService
包含業務邏輯,情況將變得越來越復雜。 您將把業務邏輯與與容器相關的邏輯分開。 以下是一些解決方法:
MessageService
提取到新服務中,該服務將被注入MessageService
。 ServiceA
的工廠,該工廠允許創建新實例,但要驗證工廠是否是正確的抽象 。 MessageService
移到ServiceA
周圍的裝飾器/代理中。 這使ServiceA
和MessageService
都忽略了生活方式的不匹配。 這涉及圍繞ServiceA
定義一個抽象,讓MessageService
依賴於此,並從裝飾器的Proccess
方法中解析具體的ServiceA
。 我同意其他答案 ,因為您不應將應用程序代碼與DI容器細節(例如IContainer
綁定在一起。
使用Autofac,可以將工廠Func<ServiceA>
(而不是ServiceA
)注入MessageService
。 只要您在容器中注冊了ServiceA
,Autofac就會為您自動生成這種工廠功能。
從Autofac的文檔中了解隱式關系類型Func<B>
:
“使用自動生成的工廠可以使您有效地調用[
Resolve<B>()
],而無需將組件綁定到Autofac。[…]“使用這種關系類型會尊重生命周期。如果將[
B
]注冊為InstancePerDependency()
並多次調用Func<B>
,則每次都會獲得一個新實例。但是,如果將[B
]注冊為SingleInstance()
並調用Func<B>
多次解析對象,您每次都會獲得相同的對象實例。”
(我的輕微改動或遺漏放在方括號中。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.