簡體   English   中英

Autofac生命周期范圍用法

[英]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周圍的裝飾器/代理中。 這使ServiceAMessageService都忽略了生活方式的不匹配。 這涉及圍繞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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM