如果您对反射的性能影响感到不安,您可以使用通用静态类和其中的私有静态字段(不共享)和一些编译魔法来“缓存”它表达式树 https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/。例如(修改您的代码以使其编译):
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; }
}
可以像这样使用:
var x = new Student();
var validations = new[]
{
new Validation
{
PropName = "Name",
IsRequired = true,
MinLength = 1,
MaxLength = 10
}
};
Validator<Student>.Validate(x, validations);
这段代码可以改进(例如如果IEnumerable<Validation>
是类本身的集合,您可以移动代码将其获取到另一个静态属性并删除相应的参数Validator.Validate
)