我有一些代码枚举一个对象,并根据其ValidationAttribute(s)记录它所发生的任何错误。
找到它们后,我希望创建一个名为RuleViolations的自定义类的集合。 RuleViolation类如下所示:
public string Message { get; set; }
public LambdaExpression Property { get; set; }
Property是lambda表达式,因此该属性不必是字符串。当我手动添加错误时,此方法起作用,但是当我只有属性的PropertyDescriptor对象时,我不确定如何指定LambdaExpression。
有人知道吗?
LambdaExpression和PropertyDescriptor网站很大程度上位于不同的世界(这让我很沮丧)。 LambdaExpression将对PropertyInfo感兴趣,而不是PropertyDescriptor。
如果有PropertyInfo,则可以通过以下方式构造一个表达式:
PropertyInfo prop = ...
ParameterExpression param = Expression.Parameter(prop.ReflectedType, "x");
LambdaExpression lambda = Expression.Lambda(
Expression.Property(param, prop), param);
您可以还会尝试按名称解析,但这不一定一样,尤其是如果您使用的是自定义类型模型(ICustomTypeDescriptor
等):
PropertyDescriptor prop = ...
ParameterExpression param = Expression.Parameter(prop.ComponentType, "x");
LambdaExpression lambda = Expression.Lambda(
Expression.Property(param, prop.Name), param);
PropertyDescriptor提供属性绑定到的Type以及属性的名称。您应该能够从中构造一个lambda表达式(未经测试):
PropertyDescriptor d = ...
Expression arg = Expression.Parameter(d.ComponentType, "arg");
LambdaExpression result =
Expression.Lambda(Expression.Property(arg, d.ComponentType, d.Name), arg);
PropertyDescriptor
更像是“虚拟”属性。它可能根本没有后备字段,因此所有以前的解决方案都将失败,除非是琐碎的情况。
但是,属性描述符提供对get(和可选的设置)方法的访问。因此,a PropertyDescriptor
读取访问权限]的确切等同项是MethodCallExpression
。
static readonly MethodInfo PropertyDescriptorGetter =
typeof(PropertyDescriptor).GetMethod(nameof(PropertyDescriptor.GetValue));
PropertyDescriptor prop = ...;
ParameterExpression param = Expression.Parameter(prop.ComponentType, "x");
MethodCallExpression value = Expression.Call(prop, PropertyDescriptorGetter, param);
LambdaExpression lambda = Expression.Lambda(value, param);