2017-06-11 15 views
2

我想弄清楚每次從容器中解析實例時如何獲取新的生命週期作用域。我想這樣做,而不需要依賴的組件需要知道Autofac。不使用Autofac命名空間的解決方案的隱式作用域

我創建具有「主服務器」(IMasterServer)分量和零個或多個「會話服務器」(ISessionServer)成分的.NET核心服務器應用程序(控制檯應用程序)。主服務器和會話服務器都有自己的IMessageBroker依賴關係。主服務器將從消息代理獲取消息時創建一個新的會話服務器。

美中不足的是,每個會話服務器實例都需要自己IMessageBroker,我不認爲我可以使用InstancePerDependency()因爲ISessionServer其他子組件也將需要訪問IMessageBroker所以消息代理必須是單個實例在會議範圍內。所以我的想法是,當主服務器產生新的會話時,它應該在新的生命週期範圍內這樣做,並且我可以使用InstancePerLifetimeScope()來註冊IMessageBroker依賴項。

所以,問題是,我怎麼能注入的ISessionServer廠發展成爲IMasterServer,使得每個工廠被調用時,一個新的生命週期範圍爲結果ISessionServer實例創建?如何做到這一點,以至於沒有任何組件需要了解Autofac?

這兩個SO問題都建議使用Owned<T>關係:

Can I create an implicit Lifetime scope within a factory?

Is it possible to create a new scope whenever a component is resolved?

然而,除非我失去了一些東西,這意味着該組件到其中的相關性將被注入(在我的情況下爲IMasterServer)需要了解Autofac,因爲它的ctor簽名必須包含Owned<T>類型。

我有什麼至今:

using Autofac.Features.OwnedInstances; 

class MasterServer : IMasterServer 
{ 
    private IMessageBroker mMessageBroker; 
    private Func<Owned<ISessionServer>> mSessionServerFactory; 

    public Master(
     Func<string, IServerMessageBroker> messageBrokerFactory, 
     Func<Owned<ISessionServer>> sessionServerFactory 
    ) 
    { 
     mMessageBroker = messageBrokerFactory("master"); 
     mSessionServerFactory = sessionServerFactory; 
    } 
} 


class SessionServer : ISessionServer 
{ 
    private IMessageBroker mMessageBroker; 
    private string mId; 

    public SessionServer(
     Func<string, IMessageBroker> messageBrokerFactory 
    ) 
    { 
     mId = Guid.NewGuid().ToString(); 
     mMessageBroker = messageBrokerFactory(mId); 
    } 
} 

你可以看到MasterServer具體類需要使用Autofac.Features.OwnedInstances命名空間,以便使用Owned<T>關係類型來定義會話工廠。

我怎樣才能使用Autofac創建一個新的生命週期範圍,每次ISessionServer通過注入MasterServer的工廠解決,而組件不需要知道任何有關特定DI容器的使用情況?

回答

0

我總是覺得讓Autofac特定的代碼滑入工廠類是兩種弊端中較少的一種。因此,如果我在你身邊,我只會使用Owned<T>課,稱它爲一天,然後繼續前進。這是一個很好的解決方案,並像Autofac一樣始終處理每一個自動化組件。

只要記得在需要時致電Dispose或您擁有的SessionServer,否則您將泄漏資源。

AFAICT Autofac方法不允許您編寫100%DI免費代碼。所以你需要在某個地方引用它。

包含Owned<T>的單個引用似乎是一個相當可接受的權衡。

讓我在你的設計中(或你所包含的部分)指出一個問題:沒有簡單的方法將ISessionServer連接到一次性作用域。

例如:您公開了一個工廠類,然後SessionServer自行發佈。以這種方式管理範圍變得困難。

一個更簡潔的方法是使用一次性成using語句:

using (var sessionServer = sessionFactory.GetServer()) 
{ 
    // do something with sessionServer. 
} 
+0

感謝您的輸入。隨着我繼續開發這個應用程序,我看到在其他地方實施有價值的Autofac功能將導致更多的組件需要了解Autofac。按照你的建議,我想我應該接受它。 –

+0

關於你將'SessionServer'封裝在使用塊中的建議,我認爲我不能這樣做,因爲'MasterServer'需要掛在'SessionServer'實例的集合上。當它被處置時它將處置它們。 –

+0

我建議你在特定的地方保留Autofac的使用。例如,您可以創建一個實現'getSessionServer()'方法的類'SessionServerHandle',並負責創建特定的Autofac範圍,實例化和處理'SessionServer'實例。簡而言之,負責管理工作單元的班級。 –

相關問題