2014-12-02 31 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