如何使用IEnumerable中的Contains方法构建LINQ表达式?

时间:2014-12-01 11:36:03

标签: c# linq ienumerable contains expressionbuilder

我正在尝试构建一个LINQ表达式,以过滤int属性中的值:

protected IQueryable<T> Some(IEnumerable<int> ids)
{
    var parameter = Expression.Parameter(typeof(T), "x");
    // "Col_id" (int property)
    var property = Expression.Property(parameter, "Col_id");

    MethodInfo method = typeof(Enumerable).
                        GetMethods().
                        Where(x => x.Name == "Contains").
                        Single(x => x.GetParameters().Length == 2).
                        MakeGenericMethod(typeof(T));

    // ids = { 2, 4, 8 } etc...
    var value = Expression.Constant(ids, typeof(IEnumerable<int>));
    var containsMethod = Expression.Call(method, property, value); // exception

    var aDelegate = Expression.Lambda<Func<T, bool>>(containsMethod, parameter);

    table = myDataContext.GetTable<T>();

    return table.AsQueryable().Where(aDelegate);
}

我正在尝试获取类似:(x => ids.Contains(x.Col_id))的内容,但会抛出异常:

  

“System.Int32”类型的表达式不能用于类型参数   'System.Collections.Generic.IEnumerable'1 [T]来自'布尔   包含[T](System.Collections.Generic.IEnumerable'1 [T],T)'方法

1 个答案:

答案 0 :(得分:3)

在我看来,你只是错误的方式得到了论据。

此:

Expression.Call(method, property, value)

表示您正在致电:

Enumerable.Contains(x.Col_id, ids)

而你想要

Enumerable.Contains(ids, x.Col_id)

所以试试吧:

var containsMethod = Expression.Call(method, value, property);

编辑:接下来,我认为你构建了错误的Contains类型参数。我怀疑你想要:

MethodInfo method = typeof(Enumerable).
                    GetMethods().
                    Where(x => x.Name == "Contains").
                    Single(x => x.GetParameters().Length == 2).
                    MakeGenericMethod(typeof(int));

毕竟,您要拨打Enumerable.Contains<int>,而不是Enumerable.Contains<SomeType>