2009-12-10 69 views
0

因此,對象模型相當複雜且層次分明。 祖父接受是由祖父工廠創建的,在其構造函數中接受祖父庫。在現有代碼庫中實現模擬倉庫

一切都很好。

現在,當爺爺需要加載它的兒童它是如何做到這一點?

它如何知道ChildFactory和ChildRepository?它不應該糾正?

但是它是如何加載它們的?我不認爲你將一個ChildFactory傳遞給祖父構造函數,就好像你有孫輩(這個應用程序所做的那樣),你也需要傳遞一個孫子工廠!

你實例某種EverythingFactory的有各種不同類型的工廠的它的內部並傳遞到每一個構造函數,他們利用他們所關心的一個嗎?

還是有一些簡單的解決方案,我只是沒有看到?

目前所有對象調用web服務來加載自己的數據,我試圖拉了這一點,並作出庫接口,可模擬來測試的目的。

編輯: 忽略工廠,我不需要他們,我想我只是過分複雜的東西。

目前的對象由散佈在對象的web服務調用的方式加載其數據和子數據。

大多數對象的構造函數被標記爲私有,並且他們有靜態方法,如「LoadByID(INT)」,以從數據庫中檢索它們。

然後當它包含它的子方法的屬性被引用,如果它是私有的「子榜」變量是空的,它調用Child.GetAllChildrenFor(本);這是Child的靜態方法,「this」是Parent類。它調用webservice,創建所有Childs,並返回它們的列表,每個列表都有一個對其父項的引用。

我知道這是不正確的...但我不知道我出了什麼問題,或者如何糾正它能夠刪除Web服務調用,並放入一個Repository接口,可以是真實還是模擬......以及我在哪些代碼中設置了哪個使用!

EDIT2: 代碼是東西沿着這些路線目前

public interface IEntity 
{ 
    int ID { get; set; } 
} 

public class Parent : IEntity 
{ 
    public int ID { get; set; } 

    private Children children; 
    public Children Children 
    { 
     get 
     { 
      if (this.children == default(Children)) 
      { 
       this.children = Children.GetChildrenFor(this); 
      } 
      return this.children; 
     } 
    } 
} 

public class Children : List<Child> 
{ 
    private Children() { } 

    public static Children GetChildrenFor(Parent parent) 
    { 
     Children children = new Children(); 

     DataSet childrenDataSet = new DataSet(); 
     using (webservice) 
     { 
      childrenDataSet = webservice.Retrieve(parent.ID) 
     } 

     if (childrenDataSet.HasRows()) 
     { 
      foreach (DataRow dr in childrenDataSet.Tables[0].Rows) 
      { 
       Child rr = Child.LoadByDataRow(dr); 
       rr.Parent = parent; 
       children.Add(rr); 
      } 
     } 

     return children; 
    } 
} 

public class Child : IEntity 
{ 
    public Parent Parent { get; set; } 
    public int ID { get; set; } 

    internal static Child LoadByDataRow(DataRow dr) 
    { 
     Child child = new Child(); 

     child.ID = dr.Field<int>("ID"); 
     child.GrandChild = GrandChildren.GetGrandChildrenFor(this); 

     return child; 
    } 
} 
+0

你應該添加一些代碼來更好地說明你在這裏做什麼。 – 2009-12-11 07:30:29

回答

1

一種方法是創建一個IRepository接口,定義爲將提供您的實體類的合同。

public interface IRepository { 
    Parent GetParent(int parentId); 
    List<Child> GetChildrenByParent(int parentId); 
    // ... 
} 

其次,改變你的實體需要在它們的構造函數的IRepository

public class Parent: IEntity { 
    private IRepository repository; 
    public Parent(IRepository repository) { 
     this.repository = repository; 
    } 
    // ... 
} 

的具體IRepository實現將包含的代碼來調用Web服務和地圖的結果,以每個實體的;它必須自己傳遞時,它構造實體,像這樣:像這樣的構造

public class ConcreteRepository: IRepository { 
    public Parent GetParent(int parentId) { 
     Parent parent = new Parent(this); 
     // Call web service, perform mapping, etc. 
    } 
} 

實體可以使用存儲庫根據需要 - 例如,在Parent.Children get訪問。您的應用程序將使用真實的存儲庫,而單元測試可以提供模擬或存根。

+0

所以我的錯誤是試圖爲每個實體創建一個存儲庫,而不是一個包含所有這些方法的存儲庫? – CaffGeek 2009-12-11 18:10:45

+0

這不是一個錯誤,只是一個設計決定 - 事實上,您仍然可以在封面下實施單獨的實體存儲庫。我只提出一個單一的存儲庫(基本上是一個抽象工廠,只要存儲庫是專門的工廠)來簡化API。 – 2009-12-11 18:51:13

+0

現在就開始工作,我看到了如何使用一個存儲庫(後來可能成爲幾個門面)使這項工作變得更加簡單。我只是用一堆靜態方法創建一個類並將任何調用拖放到Web服務中來開始它。從那裏我應該能夠重構它來實現一個接口並創建一個模擬對象......小步驟。希望下週我會有可以編寫測試的代碼... – CaffGeek 2009-12-11 20:02:30

0

創建工廠的層次結構。 ChildFactory繼承了繼承GrandfatherFactory的FatherFactory。也許工廠可以模板化,或者你可以使用抽象工廠設計模式。到這個因素碼出的靜態方法,使其模擬能夠