使用LINQKit允许选择以另一种表达内展开:
public static IQueryable<TSource> WhereIn<TSource, TProp>(
this IQueryable<TSource> query,
IEnumerable<TProp> list,
Expression<Func<TSource, TProp>> selector)
{
return query.AsExpandable()
.Where(item => list.Contains(selector.Invoke(item)));
}
如果你不想使用LinqKit,你可以写你自己的方法来编写表达式在一起。
的Compose
方法是作为与组合方法的主体替代合成方法中的参数的所有实例一样简单:
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
这使用以下方法用另一个来替换表达式的所有实例:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
现在你可以这样写:
public static IQueryable<TSource> WhereIn<TSource, TProp>(
this IQueryable<TSource> query,
IEnumerable<TProp> sequence,
Expression<Func<TSource, TProp>> selector)
{
return query.Where(selector.Compose(value => sequence.Contains(value)));
}
如果您希望确定该选择器的结果是否在列表中,那么'表达式'应该是'Expression>'。或者更好的是,它应该使用第二个通用参数。 –
Servy
2014-12-02 15:55:11