2014-12-02 50 views
1

我的扩展方法如下:在扩展方法使用动态建立查询,其中条件和动态列表

public static IQueryable<TSource> TrialBatch<TSource>(this IQueryable<TSource> sourceQuery, List<long> Ids, Expression<Func<TSource, object>> expression) 
{ 
    // Expected Code 
} 

表达可变接收将如下的“X => x.EmployeeID”

是否可以如下转换表达式?

“X => Ids.Contains(x.EmployeeID)” 这样我们就可以将其与 'sourceQuery' 结合并返回相同的。

这类似于dbContext.EmployeeIDDetails.Where(X => Ids.Contains(x.EmployeeID))ToList(); 唯一的区别是,我们将发送ID和其中条件(“X => x.EmployeeID”)动态地与相应于表中。

我使用这种类型的扩展方法的一个发展的目的,也是我很好奇,如果这是可行的。如果您有任何疑问

感谢事先请添加评论。

+1

如果您希望确定该选择器的结果是否在列表中,那么'表达式'应该是'Expression >'。或者更好的是,它应该使用第二个通用参数。 – Servy 2014-12-02 15:55:11

回答

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))); 
} 
+0

正是我即将回答的问题。虽然我会用'IEnumerable '替换'列表'。 – haim770 2014-12-02 16:00:26

+0

@Servy非常感谢你。这真的很有帮助。 – 2014-12-02 16:31:13

+0

嗨@Servy是否可以在不使用LINQKit的情况下实现它? – 2014-12-03 06:57:02