因此,我有一个简单的验证规则模式,用于对实体对象进行验证。这是我的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
我的实体对象有一个基类,它封装了执行验证的方法,如下所示:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在这就是我想要解决的真正问题。当我创建一个继承自 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)));
}
}
Run Code Online (Sandbox Code Playgroud)
请注意我在哪里创建验证规则列表。在 lambda 表达式中,我必须将“c”转换为“Client”,因为我的规则本质上是Func<object, bool>. 我已经尝试了很多方法来通过执行类似的操作来使其通用,但我总是在调用 ModelBase 类时ValidationRule<Client>遇到问题。Validate()关于如何绕过这个选角有什么想法吗?
您可以使 ValidationRule 类通用,但将 IsValid 方法的参数保留为对象,并在该方法中进行转换。这样您就可以获得泛型,而不必使 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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,lamda 表达式中参数的类型是泛型类型,因此您不必对其进行强制转换:
ValidationRules.Add(
new ValidationRule<Client>(
"Client 'Name' is required.",
c => !string.IsNullOrEmpty(c.Name)
)
);
Run Code Online (Sandbox Code Playgroud)