我的扩展方法如下:
public static IQueryable<TSource> TrialBatch<TSource>(this IQueryable<TSource> sourceQuery, List<long> Ids, Expression<Func<TSource, object>> expression)
{
// Expected Code
}
在扩展方法中接收的表达式变量将如下“x =&gt; x.EmployeeID”
是否可以按如下方式转换表达式?
“x =&gt; Ids.Contains(x.EmployeeID)”以便我们可以将它与'sourceQuery'结合起来并返回相同的内容。
这类似于dbContext.EmployeeIDDetails.Where(x =&gt; Ids.Contains(x.EmployeeID))。ToList(); 唯一的区别是我们将动态地发送Ids和where条件(“x =&gt; x.EmployeeID”)与表格相对应。
我正在使用这种类型的扩展方法用于开发目的,而且我很好奇这是否可行。如果您有任何疑问,请添加评论
提前致谢。
答案 0 :(得分:1)
使用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)));
}