Search code examples
c#reflectionlambdaexpression-trees

Get propertyinfo from lambda expression, but fails with int


What is the best way to get to all the PropertyInfo of items in a lambda expression.

i want to set a filter on a xml field in a sql database.

var FilterBase = new FilterBase<SimpleItemSubObject>()
                    .SetSimpleFilter(x => x.ID, 123)
                    .SetSimpleFilter(x => x.Test.Name, "demo3");

in de analyser, i'm able to get the propertyinfo for the Name property.

internal IEnumerable<PropertyInfo> GetExpressionList()
{
    return GetPropertyListfor(lambda.Body as MemberExpression);
}

private IEnumerable<PropertyInfo> GetPropertyListfor(MemberExpression body)
{
    var result = new List<PropertyInfo>();
    if (body != null && body.Expression != null)
    {
        result.AddRange(GetPropertyListfor(body.Expression as MemberExpression));
        result.Add((body as MemberExpression).Member as PropertyInfo);
    }

    return result;
}

this will return the propertyinfo if it's a string property. but in case of a int the analyser fails because lambda has added a convert function.

{x => Convert(x.ID)}

It added a convert function.

so what is the best method of getting the propertyinfo in this case for the x.ID. and how do i prevent the use of the convert function


Solution

  • The fact that compiler adds Convert expression indicates that you are using non generic lambda expression with object return type. Something like this:

    public class FilterBase<T>
    {
        public FilterBase<T> SetSimpleFilter(Expression<Func<T, object>> selector, object value)
        {
            // ...
            return this;
        }
    }
    

    One way to resolve the issue is to make the method generic (similar to LINQ OrderBy):

    public FilterBase<T> SetSimpleFilter<V>(Expression<Func<T, V>> selector, V value)
    

    so there will not be Convert anymore.

    Another way is to keep the method as is, and strip the first Convert if any:

    internal IEnumerable<PropertyInfo> GetExpressionList()
    {
        var body = lambda.Body;
        if (body.NodeType == ExpressionType.Convert)
            body = ((UnaryExpression)body).Operand;
        return GetPropertyListfor(body as MemberExpression);
    }