tags:

views:

67

answers:

1

So, I'm trying to figure out Expression trees. I'm trying to add in a dynamic equals to a Queryable where T is one of several different tables. I'm first checking the table contains the field I want to filter on.

ParameterExpression param = Expression.Parameter(typeof(TSource), "x");

Expression conversionExpression = Expression.Convert(Expression.Property(param, _sourceProperty), typeof(TList));

Expression<Func<TSource, TList>> propertyExpression = Expression.Lambda<Func<TSource, TList>>(conversionExpression, param);

Expression<Func<TList, TList, bool>> methodExpression = (x, y) => x.Equals(y);

ReadOnlyCollection<ParameterExpression> parameters = propertyExpression.Parameters;

InvocationExpression getFieldPropertyExpression = Expression.Invoke(
                                                propertyExpression,
                                                parameters.Cast<Expression>());

MethodCallExpression methodBody = methodExpression.Body as MethodCallExpression;
MethodCallExpression methodCall = Expression.Call(methodBody.Method, Expression.Constant(equalTo), getFieldPropertyExpression);

Expression<Func<TSource, bool>> equalsStatement = Expression.Lambda<Func<TSource, bool>>(methodCall, parameters);

return source.Where(equalsStatement);

When I execute this, I get an issue with the MethodInfo in the Call statement. It tells me;

Static method requires null instance, non-static method requires non-null instance.

I'm no master of Expression trees, but I think I understand about 75% of what I'm doing here and know what I'm trying to achieve. The TList is a bad name right now, but I took this from an example that works to produce an In statement just fine.

I'm really looking for an explanation here so I can work through the code myself, or a solution with an explanation of what I was missing.

Edit:

Ok, so after a very frustrating afternoon and still not quite feeling like I understand what I'm looking at entirely, I think I have an answer.

ParameterExpression sourceObject = Expression.Parameter(typeof(TSource), "x");

Expression<Func<TSource, bool>> check = Expression.Lambda<Func<TSource, bool>>
        (
            Expression.Equal(
            Expression.MakeMemberAccess(sourceObject, typeof(TSource).GetProperty(_sourceProperty)),
            Expression.Constant(equalTo)
        ),
        sourceObject
);

return source.Where(check);

Is anybody able to explain to me why the original just wasn't fit for what I was trying to do? I want to understand more about the actual process, but I feel I'm not picking it up as fast as I would like.

+1  A: 

Expression.Call has two sets of overloads (with lots of overloads in each). One set is for instance methods and the other set is for static methods. In those for static methods, the first argument is a MethodInfo object -- exactly like you have. For instance methods, the first argument should be an Expression representing the target (i.e. the left-hand-side of the "." in a method call.) Given the error you are receiving, it sounds like the MethodInfo represents a non-static method, and therefore you must provide an expression representing the instance as the first argument.

Kirk Woll
Thanks for the response. I marked this as the answer because it made me look at the problem the way I should have been looking at it.
Hammerstein