2012-10-11 52 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,但它会变得更加有问题。