8

I am trying to create an expression tree. I need to read data from a data table and check its columns. The columns to be checked and also the number of columns to be checked are known at run time only. The column names are given to me as a string array and and each column has a List of strings to be checked. I tried out sample expression trees , like the one below.

Here I am encountering an error.

Static method requires null instance, non-static method requires non-null instance. Parameter name: instance

at the line

inner = Expression.Call(rowexp,mi, colexp);

Kindly help me out!!!

IQueryable<DataRow> queryableData = CapacityTable
    .AsEnumerable()
    .AsQueryable()
    .Where(row2 => values.Contains(row2.Field<string>("Head1").ToString()) 
                && values.Contains(row2.Field<string>("Head2").ToString()));

MethodInfo mi = typeof(DataRowExtensions).GetMethod(
     "Field", 
      new Type[] { typeof(DataRow),typeof(string) });

mi = mi.MakeGenericMethod(typeof(string));

ParameterExpression rowexp = Expression.Parameter(typeof(DataRow), "row");
ParameterExpression valuesexp = Expression.Parameter(typeof(List<string>), "values");
ParameterExpression fexp = Expression.Parameter(typeof(List<string>), "types");
Expression inner, outer, predicateBody = null;

foreach (var col in types)
{
    // DataRow row = CapacityTable.Rows[1];

    ParameterExpression colexp = Expression.Parameter(typeof(string), "col");
    //  Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));

    inner = Expression.Call(rowexp,mi, colexp);
    outer = Expression.Call(valuesexp, typeof(List<string>).GetMethod("Contains"), inner);
    predicateBody = Expression.And(predicateBody,outer);
}

MethodCallExpression whereCallExpression = Expression.Call(
    typeof(Queryable),
    "Where",
    new Type[] { queryableData.ElementType },
    queryableData.Expression,
    Expression.Lambda<Func<DataRow,bool>>(predicateBody, new ParameterExpression[] { rowexp }));

1 Answer 1

10

It means the method call you're trying to represent is a static one, but you're giving it a target expression. That's like trying to call:

Thread t = new Thread(...);
// Invalid!
t.Sleep(1000);

You're sort of trying to do that in expression tree form, which isn't allowed either.

It looks like this is happening for the Field extension method on DataRowExtensions - so the "target" of the extension method needs to be expressed as the first argument to the call, because you actually want to call:

DataRowExtensions.Field<T>(row, col);

So you want:

inner = Expression.Call(mi, rowexp, colexp);

That will call this overload which is the way to call a static method with two arguments.

Sign up to request clarification or add additional context in comments.

2 Comments

Can you possibly elaborate a bit on the above? Why do you pass the Method info as first argument to the Expression.Call method here?
@Kobojunkie: Because that's how you tell Expression.Call what static method we're interested in. See msdn.microsoft.com/en-us/library/bb301084.aspx

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.