2010-03-21 111 views
7

我想知道如何能夠使一個表達式樹通過輸入一個以上的參數多個條件

例子:

dataContext.Users.Where(u => u.username == "Username" && u.password == "Password") 

目前的代碼,我所做的就是以下,但想做出更一般的問候條件是否爲OR或AND

public Func<TLinqEntity, bool> ANDOnlyParams(string[] paramNames, object[] values) 
    { 
     List<ParameterExpression> paramList = new List<ParameterExpression>(); 
     foreach (string param in paramNames) 
     { 
      paramList.Add(Expression.Parameter(typeof(TLinqEntity), param)); 
     } 

     List<LambdaExpression> lexList = new List<LambdaExpression>(); 
     for (int i = 0; i < paramNames.Length; i++) 
     { 
      if (i == 0) 
      { 
       Expression bodyInner = Expression.Equal(
            Expression.Property(
             paramList[i], paramNames[i]), 
             Expression.Constant(values[i])); 
       lexList.Add(Expression.Lambda(bodyInner, paramList[i])); 
      } 
      else 
      { 
       Expression bodyOuter = Expression.And(
            Expression.Equal(
            Expression.Property(
            paramList[i], paramNames[i]), 
            Expression.Constant(values[i])), 
            Expression.Invoke(lexList[i - 1], paramList[i])); 
       lexList.Add(Expression.Lambda(bodyOuter, paramList[i])); 
      } 
     } 

     return ((Expression<Func<TLinqEntity, bool>>)lexList[lexList.Count - 1]).Compile(); 
    } 

感謝

回答

2

Expression.And在這裏使用是錯誤的,它是按位和。你想要AndAlso

除了你已經知道如何構建表達式樹的機制之外,它似乎就像你。所以你真正要問的是,如何讓建築方法的調用者指定一種更復雜,更靈活的方式來組合不同的條件。

最終,爲了獲得真正的靈活性,您需要一個迷你查詢語言。解析語言以構建表達式樹。

在短期內,你可能會與一些更簡單的獲取方式:原始表達式的列表和一個布爾標誌說是否他們應該& &或||結合。

更新 - 我注意到你實際上是在將一個結果表達式編譯成一個真正的委託。這讓我很想知道爲什麼你這樣做是艱難的。爲什麼不把表達式寫成lambda表達式,就像你最初的例子那樣? (如果您使用Linq to SQL或EF,則不應編譯表達式。)

更新2 - 您可能需要的是Dynamic Linq

+0

關於爲什麼我要用艱難的方式(返回委託),原因是在設計時沒有直接訪問數據庫列名稱。我無法訪問使用datacontext.table.Where(...);因爲我已經在數據庫中加密了表名。 感謝您的回答我會尋找AndAlso方法... – Ryan 2010-03-21 12:38:40

+0

@Ryan - 見更新 - 我記得這樣做的圖書館! – 2010-03-21 12:48:25

+0

謝謝丹尼爾......我真的很感激它看起來像我需要:) – Ryan 2010-03-21 13:15:03