有這個軟件,X,它有這個非常複雜的API,我必須寫一個門面。我寫了一個類庫XClientLibrary
,並使用DI和IoC容器(Unity)製作了它。這是可能的,因爲我的庫導出服務(接口),所以用戶不知道使用構造函數DI的具體類。他們也不知道IoC容器。DI:在使用子容器時註冊 - 解析 - 發佈
「根服務」是一個IXClient
實例,應該運行應該創建一次並使用它。 (這是一個桌面應用程序btw)。 X客戶端允許用戶連接到X主機,如果他們知道URL。 X主機允許用戶訪問主機的服務及其服務等(非常複雜的對象圖)。這是示例用戶代碼:
// 1. app startup
XClientProvider provider = new XClientProvider(); // call only once per app
IXClient xClient = provider.GetClient(); // always returns the same instance
xClient.Startup();
// 2. app normal usage
IXHost host = xClient.ConnectToHost(new Uri("http://localhost")); // return new instance each time
IXService1 service = host.GetThis();
IXService2 otherService = service.DoThat();
...
host.Dispose();
// get another host, consume it, dispose it, etc
...
// 3. app shutdown
xClient.Shutdown();
provider.Dispose();
我試圖跟蹤Mark塞曼的建議,以實現這一點,但我不知道它們是否適用於一個類庫了。客戶端提供程序是組合根,這是唯一使用IoC容器的位置。該組合物根如下RRR pattern:
- 容器上
new XClientProvider()
創建和配置 - 主叫
GetClient()
- 容器被設置在
provider.Dispose()
事情當容器可解決IXClient
變得複雜時該容器被要求解決IXHost
。它的實現:
internal class XHost : IXHost
public XHost(Uri uri, IXService1 service1)
客戶端應該創造XHost
實例,所以它的實現需要知道如何創建IXService1
:
internal class XClient : IXClient
public XClient(Func<IXService1> xService1DelegateFactory)
調用委託工廠達到它創建了一個IXService1
容器。此外,讓我們說,在這個圖中有一類XComponent7
要求其用於創建主機的確切IXService1
實例:
internal class XComponent7 : IXService7
public XComponent7(Func<IXService1> service1DelegateFactory)
我不得不使用Func
處理循環依賴。容器應該配置成一旦解決了IXService1
,每當要求解決IXService1
時,它將提供相同的實例。
現在變得非常複雜。我想限制這種行爲「per host resolve」,這意味着一旦創建了一個主機,容器應該創建一個IXService1
並緩存它並將其提供給任何需要它的組件,只要該組件是主機對象圖的一部分。當處理主機時,我還需要一種方法來處置所有組件。
我在想我可以使用子容器來做到這一點。當用戶撥打ConnectToHost
時,我可以創建一個,請求它解析主機並將其置於主機處置。主容器仍然存在,直到他們在供應商處撥打Dispose
纔會被處置。
問題是,我認爲它打破了RRR模式。所以我想知道如何使用小孩容器時RRR的作品...也許IXHost
是另一個「根」,可以由組合根直接解決?或者也許有一個非常聰明的Unity終身經理可以做我需要的東西?
在我甚至試圖弄清楚你的對象圖和你想要做什麼之前:你能解釋一下你的意思是客戶端,主機,服務和組件嗎?對我來說,客戶似乎可以訪問你所謂的主機(比如某種類型的註冊表)。這些主機提供您打電話的服務實際上做些什麼? – 2012-01-16 21:38:08
@Sebastian服務和組件定義在這裏(http://stw.castleproject.org/Windsor.Services-and-Components.ashx)。主機是某種DNS主機,客戶端是訪問主機的手段。我的用戶不能'var host = new Host(uri)',所以我必須爲他們提供另一種方式:'var host = client.ConnectToHost(uri)'。我不確定「客戶」是否是一個好名字... – Suiden 2012-01-16 21:55:30