我們的客戶擁有一個龐大的遺留系統,正在從.NET 1.1升級到.NET 4.0。除此之外,還將把底層框架移植到WCSF 2010用於Web應用程序,以及Enterprise Library 5.0或Iou1作爲基礎企業框架。除了這些框架外,還有DI設施。在傳統應用系統中應用DI實踐
WCSF有效地強制MVP和模塊設計依賴於ObjectBuilder及其屬性,因此Web應用程序升級遵循該模式。
Web應用程序在應用程序層(通過WCF)使用額外的應用程序服務。由於底層框架已經成爲企業庫,Unity應用程序塊已經「免費滑入」了。但是現有的編碼風格仍然是傳統的,因此與web層不同,它沒有從根本上切換到DI。
在應用層的典型層
- 商業門面(BF) - 公衆公開粗粒度的業務功能,控制交易。
- 業務組件(BC) - 由門面方法協調的粒度邏輯組件,用於執行事務中的實際工作。
- 數據訪問(DA) - 閱讀業務組件/寫數據
爲什麼我的風格上面提到的仍然是舊的,因爲各層之間的服務通信發生在通過傳遞數據集(他們是巨大的)通過網絡。這個DataSet被傳遞給每個對象的構造函數。例如。僞代碼
BF.SomeExposedMethod(StrongTypeDS ds)
{
this.BeginTransaction();
BizComp bc = new BizComp(ds);
bc.ShareTransaction();
bc.DoWork();
this.CommitTransaction();
}
BC.DoWork()
{
DataAccess da = new DataAccess(this.transaction, this.ds);
// perform work
da.SaveWork(this.ds);
}
更重要的是這些類的構造是基於它們的父抽象類的風格;他們期望在實例化時接收數據集。
我一直在閱讀馬克塞曼的DI在NET書和各種其他公共互聯網來源有關DI問題。從所有這些討論中,我似乎都明白,DI看起來不錯,它準備好了準備開展工作的清潔對象的圖表。清理我的意思是清空上下文數據。這些遺留代碼模式的構造函數從一開始就期望正確的工作數據和上下文。
如果我正確理解Composition Root的原則,則必須重新設計構造函數和方法,以便通過屬性傳遞上下文DataSet。我不清楚DI容器(在這種情況下,Unity是如何)可以自己弄清楚DataSet注入的內容。當然,它不能是一個全新的DataSet。在這個開發階段(我沒有直接參與這個項目,但是從旁邊支持),我將無法建議對實例化Facade對象之前的WCF實現進行基本更改,使其成爲Composition Root。
此外,我還沒有收集關於DI如何適用於基於運行條件實例化對象的重要建議?根據數據的執行狀態,可能會實例化其他對象,並且類型可能因數據類別而異。這似乎是在這個應用程序中引入某種級別的DIP和DI實踐的最簡單方法,就是將Unity容器作爲服務定位器使用;只根據需要在執行時抓取實例。
UPDATE來回答
基於馬克·塞曼的建議,我已經制作了以下POC
BF有統一的容器。雖然我成功地嘗試了Unity.Wcf包,但我也對每個BF都做了第二個最接近的事情,一個Composition根,其中每個Facade方法將調用容器來解析執行該方法工作所需的對象圖。 (這是更現實這種環境下可能會選擇給情景模式。)
static ExampleBF()
{
container = new UnityContainer().LoadConfiguration();
}
BF得到了解決IBCFactory,這將實例化一個具體的BC與通過現場上下文數據。
DataSet IExampleService.GetProducts(DataSet ds)
{
IExampleBC bc = container.Resolve<IBCFactory>().CreateBC(ds);
// GetProducts() takes no parameter because DataSet already passed in on construction.
return bc.GetProducts();
}
BCFactory通過構造器注入接收IDACFactory。它交給每個實例化的BC。
public BCFactory(IDACFactory DACFactory)
{
this.DACFactory = DACFactory;
}
IExampleBC IBCFactory.CreateBC(DataSet ds)
{
return new ExampleBC(this.DACFactory, ds);
}
BC將依靠IDACFactory爲其提供DAC。
DataSet IExampleBC.GetProducts()
{
IExampleDAC dac = this.dacFactory.CreateDAC(this.ds);
return dac.GetProducts();
}
DACFactory類似地基於上下文數據實例化DAC。
IExampleDAC IDACFactory.CreateDAC(DataSet ds)
{
return new OrderDAC(ds);
}
當然的代碼庫的複雜的現實情況是幅度較大的方式,但這個簡單的例子應該展示DI概念,他們希望就足夠了。
我確實有這本書,但並沒有像書中那麼深入。我不「擁有」代碼庫,因此對它沒有真正的權威;我只能研究現有的模式並提出建議。在審查中,我越來越意識到單靠DI是不足以改進這些代碼結構的;看起來這將是一個漫長的旅程。 :-) – icelava 2012-02-10 03:14:09
真正的實體和數據對象是數據集;所有這些業務類都處理DataSet中的數據。 – icelava 2012-02-10 03:24:26
從您的建議更新狀態,謝謝。 – icelava 2012-02-14 03:00:08