get expression of method in Expression tree
我想在表达式树中创建以下查询:
1 2 3 | var test = from datarow in tempResults where datarow.Field<String>("ColumnName") =="Column" select datarow; |
如何创建表达式:
1 | datarow.Field<String>("ColumnName")? |
我什么都试过了,我甚至一直在为expression.call方法获取字段的MethodInfo。字段是DataRowExtensions的扩展方法。
我必须为此使用expression.call()吗?我怎样才能得到卫理公会信息?有没有更简单的方法?
我试过:
ParameterExpression dataRow = Expression.Parameter(typeof(DataRowExtensions),"dataRow");
Expression left = Expression.Call(dataRow, typeof(DataRowExtensions).GetMethod("Field"));
但它不起作用。
我想在iqueryable tempresults内的数据上创建动态过滤器。
用户将选中GUI上的复选框,该复选框将向tempresults中的数据添加"where"表达式。当用户选择"column"时,我想显示columnname="column"所在的数据行。
这就是为什么我需要创建Where表达式。但我对卫理公会的事很感兴趣。我也试过这个:
1 | MethodInfo FieldStringMethodInfo = typeof(DataRowExtensions).GetMethod("Field", BindingFlags.Public | BindingFlags.Static); |
但它也不管用。
还有其他方法吗?
在评论中澄清后的替换回答:
为了连续地构建额外的过滤器,您不需要表达式树;您可以多次调用
1 2 3 4 5 6 7 | 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); } |
唯一要注意的是"捕获"问题;确保不要重复使用任何
对于委托组合的示例(来自注释)-请注意,我在这里删除了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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); } } } |
(原始答案)
实际上,Linq的变体不会使用表达式树…它将使用委托;但是如果您真的想要,您可以构建树并编译它…不过,我不知道你为什么要这样做。你想做什么?我来举个例子…
给你,这使用了表达式树,但是我想不出一个好的理由来做这个,除了证明你可以!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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()); } } |