我正在使用一种模式,其中实现接口的具体 ViewModel 被传递到存储库,然后填充 ViewModel 对象,但仅使用接口。这使得存储库更重一些,但允许在不同场景中重用存储库。例如,具体实现可以是 MVC ViewModel,也可以是实现接口的 asp.net Page,其中每个属性的 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,存储库可以获取集合并以无效的方式对其进行修改。我认为这些情况很少见,因为团队会知道这种模式,但是完全没有陷阱总是很好的,而不是每个人都必须记住不要介入的陷阱。
事实上,它感觉有点脏。
当这样做的方法只知道接口时,您将如何设计/公开将具体类型实例化并添加到集合中的能力?