这是一个使用S#arp架构的MVC 3项目。
我的域有几个继承NamedEntity
的对象,这是一个扩展Entity
并定义string Name
属性的抽象类。
所有这些对象都分享了这样一个事实:它们必须是对象类型的唯一名称。
鉴于这些对象的集合相对较小(200将是极端情况),我不介意往返数据库以检查是否存在重复。
我的问题是,在保持DRY的同时轻松验证这一点的最佳方式是什么?
我经历了六次迭代,并不是特别喜欢它们中的任何一种。我尝试在ViewModel上创建[ValidUniqueName]
属性,并且可以键入ViewModel EditViewModel<T> where T: NamedEntity
。问题在于,由于Generic,该属性不知道要与之通信的正确的存储库/任务对象。
要解决此问题,我尝试在ViewModel中创建INamedEntityTasks<T>
引用,并从ValidationContext
为ValidUniqueName
属性访问它。这不能按预期工作,因为属性不是通用的(它不可能),因此它不知道如何正确地将ValidationContext.ObjectInstance
转换回可用的东西。
此时,我唯一能想到的就是创建单独的[ValidUniqueFoo]
[ValidUniqueBar]
等属性,这似乎很糟糕。或者,我可以在每个控制器中进行验证,但看起来同样糟糕。
答案 0 :(得分:0)
您可以简单地将重载的构造函数添加到[ValidUniqueName]
吗?或者我完全错过了这一点?
修改强>
您可以将两个类型参数传递给ViewModel
类似
ViewModel<T, TRepository>
答案 1 :(得分:0)
目前看起来它似乎涉及肮脏的黑客或一些严重复杂的代码(见其他答案)。必须写
并不可怕public class ValidUniqueCityAttribute : ValidationAttribute {
public override bool IsValid(object value)
{
if (value == null || !(value is CityCreateOrEditViewModel)) return base.IsValid(value);
INamedEntityTasks<City> tasks = new NamedEntityTasks<City>();
CityCreateOrEditViewModel vm = value as CityCreateOrEditViewModel;
return !tasks.CheckForDuplicateName(vm.Entity.Id, vm.Entity.Name);
}
}
对于每个NamedEntity,我们复制&amp;粘贴,搜索&amp;替换...是的,这是多余的,但它确实具有允许更大灵活性的优势,例如,如果我们想要以类别之外的其他方式验证城市名称(例如查找所有城市中的所有城市的主列表)例如,给定的状态,虽然这是完全做作和可怕的做法:))。