So I have a simple validation rule pattern that I'm using to do validation on entity objects. Here is my ValidationRule class:
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);
}
}
I have a base class for my entity objects that encapsulate the methods to perform validation that looks like this:
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;
}
}
And now here's the real problem I'm trying to solve. When I create a new class that inherits from ModelBase adding validation rules is a little awkward. For example:
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)));
}
}
Notice where I'm creating the validation rules list. Inside the lambda expression I have to cast "c" to "Client" because my rule is essentially Func<object, bool>
. I've tried many ways to make this generic by doing something like ValidationRule<Client>
but I always run into problems with calling Validate()
in the ModelBase class. Any ideas on how to get around this casting?