创建 Where 查询的 LINQ 扩展方法

LINQ extension method to create Where query

我正在尝试创建一个扩展方法,该方法可用于 LINQ-to-Object 和 LINQ-to-Entities 以创建功能性 Where 查询。最终会有更多内容,但首先我遇到了一个问题,就是获取采用 lambda 列选择的方法并将其用作 Contains() 调用的基础。我已经能够为 LINQ-to-Objects 做一些工作,但是当我尝试将它用于 LINQ-to-Entities 时出现问题。

以下是适用于 LINQ-to-Objects 的方法:

public static IQueryable<T> WhereContains<T>(this IQueryable<T> query, Expression<Func<T, string>> column, IList<string> values)
{
    return query.Where(o => values.Contains(column.Compile().Invoke(o)));
}

如果这是 运行 反对 Entity Framework 我得到一个异常说明

LINQ to Entities does not recognize the method...

我觉得这将需要使用 ExpressionVisitor,但我一直无法弄清楚它需要如何连接。有没有人能够做到这一点?

更新:

我认为这不是重复,因为 xanatos 提供的答案显示了一种无需使用 ExpressionVisitor 即可实现此目的的直接方法。

是的,您必须稍微修改 Expression,但不需要 ExpressionVisitor。就简单多了。

public static IQueryable<TSource> WhereContains<TSource, TResult>(this IQueryable<TSource> query, Expression<Func<TSource, TResult>> column, IList<TResult> values)
{
    MethodInfo iListTResultContains = typeof(ICollection<>).MakeGenericType(typeof(TResult)).GetMethod("Contains", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(TResult) }, null);

    var contains = Expression.Call(Expression.Constant(values), iListTResultContains, column.Body);

    var lambda = Expression.Lambda<Func<TSource, bool>>(contains, column.Parameters);

    return query.Where(lambda);
}

请注意,我将其扩展了一些以涵盖更多 string