If you are disturbed by performance hit of the reflection you can “cache” it using generic static classes and private static fields in them (which are not shared) and some compilation magic using expression trees. For example (modified your code to make it compile):
public static class Validator<T>
{
private static readonly Dictionary<string, Func<T, object>> propGetters;
static Validator()
{
propGetters =
typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.GetGetMethod() != null)
.ToDictionary(p => p.Name, p =>
{
var par = Expression.Parameter(typeof(T));
var access = Expression.Property(par, p);
var lambda = Expression.Lambda<Func<T, object>>(Expression.Convert(access, typeof(object)), par);
return lambda.Compile();
});
}
public static bool Validate(T c, IEnumerable<Validation> v)
{
return v.All(v => v.Validate(propGetters[v.PropName](c)));
}
}
class Student
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Validation
{
public string PropName { get; set; }
public bool IsRequired { get; set; }
public int? MaxLength { get; set; }
public int? MinLength { get; set; }
public bool Validate(object propValue)
{ return false; }
}
Which can be used like this:
var x = new Student();
var validations = new[]
{
new Validation
{
PropName = "Name",
IsRequired = true,
MinLength = 1,
MaxLength = 10
}
};
Validator<Student>.Validate(x, validations);
This code can be improved(for example if IEnumerable<Validation>
is collection on the class itself you can move code getting it to another static property and remove corresponding parameter of Validator.Validate
)