开发者

How to get a lambda expression from a PropertyDescriptor

I have some code that enumerates over an object and records any errors it has based on its ValidationAttribute(s).

As it finds them I wish to create a collection of a custom class named RuleViolations. The RuleViolation class looks like this:

public string           Message  { get; set; }
public LambdaExpression Property { get; set; }

Property is a lambda expression so that the p开发者_开发百科roperty doesn't have to be a string. THis works when I manually add errors but I'm not sure how to specify the LambdaExpression when all I have is the property's PropertyDescriptor object.

Does anyone know how?


LambdaExpression and PropertyDescriptor site largely in different worlds (much to my initial frustration). LambdaExpression is going to be interested in PropertyInfo, not PropertyDescriptor.

If you have the PropertyInfo, you can construct an Expression via:

PropertyInfo prop = ...
ParameterExpression param = Expression.Parameter(prop.ReflectedType, "x");
LambdaExpression lambda = Expression.Lambda(
    Expression.Property(param, prop), param);

You can also attempt to resolve by name, but this is not necessarily the same, especially if you are using a custom type model (ICustomTypeDescriptor etc):

PropertyDescriptor prop = ...
ParameterExpression param = Expression.Parameter(prop.ComponentType, "x");
LambdaExpression lambda = Expression.Lambda(
    Expression.Property(param, prop.Name), param);


A PropertyDescriptor provides the Type the Property is bound to, and the Name of the Property. You should be able to construct a lambda expression from that (untested):

PropertyDescriptor d = ...

Expression arg = Expression.Parameter(d.ComponentType, "arg");

LambdaExpression result =
    Expression.Lambda(Expression.Property(arg, d.ComponentType, d.Name), arg);


A PropertyDescriptor is more like a "virtual" property. It may not have a backing field at all, so all previous solutions will fail except for trivial cases.

However, a property descritor provides access to a get (and optionally set) method. So the exact equivalent of a PropertyDescriptor read access is a 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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜