使用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