将List.Contains转换为表达式树

时间:2017-10-07 13:10:40

标签: c# linq lambda expression-trees

相关:

Create a Lambda Expression With 3 conditions

Convert Contains To Expression Tree

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

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

我写这段代码:

List<byte?> lst = new List<byte?>{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<T, bool>>(body, param);
return lambda;

我收到错误:

  

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

请帮我找到问题。

由于

2 个答案:

答案 0 :(得分:2)

Convert Contains To Expression Tree的区别在于我们调用了string 实例 Contains方法,而在这里我们需要调用 static < / strong>泛型方法Enumerable.Contains

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

可以使用另一个Expression.Call overload

来实现
public static MethodCallExpression Call(
    Type type,
    string methodName,
    Type[] typeArguments,
    params Expression[] arguments
)
像这样:

// Enumerable.Contains<byte?>(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)
);

答案 1 :(得分:1)

问题是您已将两个参数切换为Expression.Call,您的代码正在尝试创建无意义的表达式o.Status.Contains(lst)

您需要切换两个参数:

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

这假设您使用的LINQ提供程序理解List<T>.Contains()。如果您需要Enumerable.Contains(),请查看Ivan Stoev的回答。