Get a method expression in an expression tree

I want to create the following query in expression trees:

var test = from datarow in tempResults
           where datarow.Field<String>("ColumnName") == "Column"
           select datarow;

      

How to create an expression:

datarow.Field<String>("ColumnName")?

      

I tried everything, even got stuck in getting the MethodInfo field for the Expression.Call method. The field is an extension of the DataRowExtentions method.

Should I use Expression.Call () for this? How do I get the MethodInfo? is there an easier way to do this?

I tried:

ParameterExpression dataRow = Expression.Parameter (typeof (DataRowExtensions), "dataRow"); Expression left = Expression.Call (dataRow, typeof (DataRowExtensions) .GetMethod ("Field"));

but that won't work.


I want to create dynamic filters for data inside IQueryable tempResults.

The user will check the boxes in the GUI, which will add "Where" expressions to the data in tempResults. when user selects "Column" I want to present DataRows where ColumnName = "Column".

so I need to create a where clause. but I am so stuck with the method. I tried it too:

MethodInfo FieldStringMethodInfo = typeof(DataRowExtensions).GetMethod("Field", BindingFlags.Public | BindingFlags.Static);

      

but it doesn't work either.

Are there any other ways to do this?

+2


source to share


1 answer


Fallback answer after clarification in comments:

You do not need expression trees to create additional filters sequentially; you can call it .Where

multiple times (as needed, once for each search term) - for example:

IEnumerable<DataRow> query = tempResults.AsEnumerable();
if(!string.IsNullOrEmpty(value1)) {
    query = query.Where(row => row.Field<string>("Col1") == value1);
}
if (!string.IsNullOrEmpty(value2)) {
    query = query.Where(row => row.Field<string>("Col2") == value2);
}

      

The only thing to look at is the "capture" problem; don't forget to reuse any of value1

, value2

etc. - otherwise, the last value will be applied to filters earlier ...


For an example of a combination of delegates (from comments) - note that I've dropped the aspect here DataTable

to make the example shorter (it will work the same):

public static class Predicate {
    public static Func<T, bool> OrElse<T>(
            this Func<T, bool> lhs, Func<T, bool> rhs) {
        return lhs == null ? rhs : obj => lhs(obj) || rhs(obj);
    }
    public static Func<T, bool> AndAlso<T>(
            this Func<T, bool> lhs, Func<T, bool> rhs) {
        return lhs == null ? rhs : obj => lhs(obj) && rhs(obj);
    }
}
class Data {
    public string Color { get; set; }
}
class Program {
    static void Main() {
        bool redChecked = true, greenChecked = true; // from UI...
        List<Data> list = new List<Data>() {
            new Data { Color = "red"},
            new Data { Color = "blue"},
            new Data { Color = "green"},
        };
        Func<Data, bool> filter = null;
        if (redChecked) {
            filter = filter.OrElse(row => row.Color == "red");
        }
        if (greenChecked) {
            filter = filter.OrElse(row => row.Color == "green");
        }
        if (filter == null) filter = x => true; // wildcard

        var qry = list.Where(filter);

        foreach (var row in qry) {
            Console.WriteLine(row.Color);
        }
    }
}

      




(original answer)

Actually, this LINQ variant won't use an expression tree ... it will use a delegate; but you can build a tree and compile it if you really want ... I'm not sure why you would do this. What do you want to do? I'll knock out an example ...


Here you go; this uses an expression tree, but I can't think of any good reason for this other than to prove that you can!

public static class MyExtensions
{
    public static IQueryable<TRow> Where<TRow, TValue>(
        this IQueryable<TRow> rows,
        string columnName, TValue value)
        where TRow : DataRow
    {
        var param = Expression.Parameter(typeof(TRow), "row");
        var fieldMethod = (from method in typeof(DataRowExtensions).GetMethods()
                           where method.Name == "Field"
                           && method.IsGenericMethod
                           let args = method.GetParameters()
                           where args.Length == 2
                           && args[1].ParameterType == typeof(string)
                           select method)
                           .Single()
                           .MakeGenericMethod(typeof(TValue));
        var body = Expression.Equal(
            Expression.Call(null,fieldMethod,
                param,
                Expression.Constant(columnName, typeof(string))),
            Expression.Constant(value, typeof(TValue))
        );
        var lambda = Expression.Lambda<Func<TRow, bool>>(body, param);
        return rows.Where(lambda);

    }
}
class Program
{
    static void Main(string[] args)
    {
        DataTable tempResults = new DataTable();
        tempResults.Columns.Add("ColumnName");
        tempResults.Rows.Add("foo");
        tempResults.Rows.Add("Column");

        var test = tempResults.AsEnumerable().AsQueryable()
                   .Where("ColumnName", "Column");
        Console.WriteLine(test.Count());

    }
}

      

+2


source







All Articles