2012-10-11 55 views
1

我正在使用一種模式,其中實現接口的具體ViewModel被傳遞給存儲庫,然後該存儲庫填充ViewModel對象,但僅使用接口。這使得存儲庫稍重一些,但允許存儲庫在不同情況下重用。例如,具體實現可以是MVC ViewModel,或者它可以是實現接口的asp.net Page,其中每個proeprty的set訪問器實際上將值放入GUI中,例如文本框。接口的實現作爲映射並消除了複製的額外步驟。在廣泛使用AutoMapper並且現在暴露於這種模式之後,我更喜歡這一點。通過接口/工廠填充集合?

public interface IPerson 
{ 
    int Id{set}; 
    string Name{set}; 
    string Address{set}; 
} 

public class PersonRepository 
{ 
    GetPerson(int id, IPerson person) 
    { 
     //query...  
     person.Id = result.Id;  
     person.Name = result.Name; 
     person.Address = result.Address;  
    } 
} 

//...controller action 
PersonViewModel person = new PersonViewModel(); 
rep.GetPerson(5, person); 

雖然這裏有棘手的部分。有時ViewModel需要一個項目集合,可以是索引頁面,也可以是下拉菜單,或者顯示一組嵌套的子對象。存儲庫不能實例化一個接口,所以我們提供它是一個工廠。與協方差一段時間戰鬥,我放棄了暴露任何類型的集合,並結束了與這兩個創建並添加收藏項目的方法:

public interface IPerson 
{ 
    //... 
    IJobRole CreateAndAddJobRole();  
} 

public class PersonViewModel:IPerson 
{ 
    //collection not part of the interface 
    ICollection<JobRoles> JobRoles {get;set;} //= new List<JobRoles> in constructor 

    public CreateAndAddJobRole() 
    { 
    role = new JobRole(); 
    JobRoles.Add(role); 
    return role; 
    } 
} 

public class PersonRepository 
{ 
    GetPerson(int id, IPerson person) 
    { 
     //... 
     foreach(var result...) 
     { 
     IJobRole role = person.CreateAndAddJobRole(); 
     role.SomeProperty = //... 
     } 
    } 
} 

顯然,我可能有一個處理的工作角色倉庫實際上是填充集合的人。我可能實際上有更多的粒度接口,以便不同的存儲庫負責填充他們處理的數據。 ViewModel只會實現多個接口。也就是說,我意識到還有改進的餘地,但我特意在這裏,因爲我沒有處理收集問題的好主意。

這種設計的一個好處是沒有可能被倉庫濫用的集合。從來沒有猜測誰是負責實例化集合本身,誰負責它,或者如果你只是一個getter,存儲庫可以獲取集合並以無效的方式修改它。我認爲這些將是罕見的事件,因爲球隊會知道這種模式,但總是很好,根本沒有陷阱,而不是在那裏有每個人都必須記住不要插手的陷阱。

事實上,感覺有點不舒服。

如何設計/展示具體類型被實例化並添加到集合中的能力,當這樣做的方法只知道接口時?

+1

是'IPerson ()其中TJob:IJobRole'完全可行嗎? – Bobson

+0

這是可能的,我想,但我很好奇你要去那裏。這是否會使IPerson可以爲該集合聲明一個具體的類型,即'new TJob()'? (花了我幾分鐘)如果是這樣,這很有意義,但可能會混淆ViewModel上的大量集合,因爲這可能與IPerson 類似。也許可以通過讓其他倉庫負責他們自己的類型來解決(例如IJobRole)。給我另一個想法。 – AaronLS

+0

非常。我會把它充實成一個完整的答案。 – Bobson

回答

1

這聽起來像你最好的選擇就是讓每個接口通用,並傳遞類型的集合。例如:

public interface IPerson<TJob> where TJob : IJobRole 
{ 
    ICollection<TJob> JobRoles {get;set;} 
    void AddJobRole(TJob role); 
} 

public JobRole : IJobRole 
{ 
} 

public class PersonViewModel:IPerson<JobRoles> 
{ 
    //collection is now part of the interface 
    ICollection<JobRoles> JobRoles //= new List<JobRoles> in constructor 

    public void AddJobRole(JobRoles role) 
    { 
    JobRoles.Add(role); 
    } 
} 

public class PersonRepository 
{ 
    GetPerson(int id, IPerson<JobRoles> person) 
    { 
     //... 
     foreach(var result...) 
     { 
     person.AddJobRole(new JobRole { 
      SomeProperty = //... 
      SomeOther = //... 
     } 
     } 
    } 
} 

當然,這是假定你知道你想要哪種類型的IPerson<>當你調用GetPerson()。如果你需要它來處理任何IPerson,但它會變得更加有問題。