所以我有一个简单的验证规则模式,我用它来对实体对象进行验证。这是我的ValidationRule类:
public class ValidationRule {
public Func<object, bool> Rule { get; set; }
public string ErrorMessage { get; set; }
public ValidationRule(string errorMessage, Func<object, bool> rule) {
Rule = rule;
ErrorMessage = errorMessage;
}
public bool IsValid(object obj) {
return Rule(obj);
}
}
我有一个实体对象的基类,它封装了执行如下所示验证的方法:
public abstract class ModelBase {
private List<ValidationRule> _validationRules;
public List<ValidationRule> ValidationRules {
get {
if (_validationRules == null)
_validationRules = new List<ValidationRule>();
return _validationRules;
}
set { _validationRules = value; }
}
public ValidationResult Validate() {
var result = new ValidationResult();
rules.ForEach(r => {
if (!r.IsValid(this))
result.Errors.Add(
new ValidationError(r.ErrorMessage, r.PropertyName));
});
return result;
}
}
现在这是我正在努力解决的真正问题。当我创建一个继承自ModelBase的新类时,添加验证规则有点尴尬。例如:
public class Client : ModelBase {
public int ID{ get; set; }
public string Name { get; set; }
public Address MailingAddress { get; set; }
public Client() {
CreateValidationRules();
}
private void CreateValidationRules() {
ValidationRules.Add(new ValidationRule("Client 'Name' is required.",
c => !string.IsNullOrEmpty(((Client)c).Name)));
}
}
请注意我在哪里创建验证规则列表。在lambda表达式中,我必须将“c”转换为“Client”,因为我的规则基本上是Func<object, bool>
。我已经尝试了很多方法通过像ValidationRule<Client>
之类的东西来制作这个泛型,但我总是遇到在ModelBase类中调用Validate()
的问题。关于如何绕过这个演员的任何想法?
答案 0 :(得分:4)
您可以使ValidationRule类通用,但将IsValid方法的参数保留为对象并在方法中执行转换。这样你就可以获得泛型而无需使用ModelBase泛型。
您还需要一个ModelBase接口,以便能够在不知道其实际类型的情况下保留验证规则列表。然后只需将列表的类型和ModelBase中的属性更改为IValidationRule。
(注意:您可以在属性上使用私有设置器将它们设置为只读。)
public Interface IValidationRule {
bool IsValid(object);
}
public class ValidationRule<T> : IValidationRule {
public Func<T, bool> Rule { get; private set; }
public string ErrorMessage { get; private set; }
public ValidationRule(string errorMessage, Func<object, bool> rule) {
Rule = rule;
ErrorMessage = errorMessage;
}
public bool IsValid(object obj) {
return Rule((T)obj);
}
}
现在,lamda表达式中的参数类型是泛型类型,因此您不必强制转换它:
ValidationRules.Add(
new ValidationRule<Client>(
"Client 'Name' is required.",
c => !string.IsNullOrEmpty(c.Name)
)
);
答案 1 :(得分:1)
我怀疑ModelBase也需要变得通用。我不清楚这里到底发生了什么 - 对于每个客户端,验证规则是否相同?验证规则感觉它们应该与整个类型相关联,而不是与类型的单个实例相关联。无可否认,它们将针对单个实例进行验证。
我想知道您是否应该使用Validator<T>
类型,并创建(一次)Validator<Client>
,然后可以对Client
的任何实例进行验证。