将List.Contains转换为表达式树

相关:

使用3个条件创建Lambda表达式

转换包含到表达式树

在我上一个问题的下面,我遇到了这个查询,我想编写Expression Tree版本:

 List lst = new List{1,2}; from a in myTbl where a.Age = 20 && lst.Contains(a.Status) select a 

我写这段代码:

 List lst = new List{1,2}; var param = Expression.Parameter(typeof(T), "o"); var body = Expression.AndAlso( Expression.Equal( Expression.PropertyOrField(param, "Age"), Expression.Constant(20) ), Expression.Call(Expression.PropertyOrField(param, "Status"), "Contains", Type.EmptyTypes, Expression.Constant(lst))); var lambda = Expression.Lambda<Func>(body, param); return lambda; 

我收到错误:

“类型’System.Nullable`1 [System.Byte]’上没有方法’包含’。”

请帮我找到问题所在。

谢谢

问题是你已经将两个参数切换到Expression.Call ,你的代码试图创建无意义的表达式o.Status.Contains(lst)

你需要切换两个参数:

 Expression.Call(Expression.Constant(lst), "Contains", Type.EmptyTypes, Expression.PropertyOrField(param, "Status")) 

这假设你正在使用的LINQ提供程序理解List.Contains() 。 如果你需要Enumerable.Contains() ,那么看看Ivan Stoev的答案。

转换包含到表达式树的区别在于我们在那里调用了一个string 实例 Contains方法,而在这里我们需要调用一个静态generics方法Enumerable.Contains

 public static bool Contains( this IEnumerable source, TSource value ) 

它可以通过使用另一个Expression.Call overload来实现:

 public static MethodCallExpression Call( Type type, string methodName, Type[] typeArguments, params Expression[] arguments ) 

像这样:

 // Enumerable.Contains(lst, a.Status) var containsCall = Expression.Call( typeof(Enumerable), // type "Contains", // method new Type[] { typeof(byte?) }, // generic type arguments (TSource) Expression.Constant(lst), // arguments (source) Expression.PropertyOrField(param, "Status") // arguments (value) );