2010-08-10 209 views
4

可以說我有這有以下形式:Lambda表達式和搜索

名稱:文本框
電子郵件:文本框
年齡:文本框

現在我想要得到的客戶集合基於此過濾器文本框

所以我想用類似的東西:

List<customer> customers = getCustomerswhere(c=>c.name == txtName.Text && Email == txtEmail.Text); 

現在的我當然不知道,他將填補,而他不會這麼

if (txtName.Text.trim() != "") 
    //something like c=>c.Name == txtName.text; 
if (txtEmail.Text.trim() != "") 
    //something like and c=>c.Email == txtEmail.text; 

我如何做到這一點!我不能連接lambda表達式,我知道我可以使用動態表達式,但我認爲有更簡單的方法?任何想法如何實現這一點?


好,我想這:

 Func<Customer,bool > a = (bb) => bb.fullName == "asdfsd"; 
     Func<Customer, bool> b = c => c.lastName == "sdas"; 
     Func<Customer, bool> cc = c => a(c) && b(c); 

現在談到另一個問題

通過CC方法IM來期待Expression<Func<T, bool>> expression

所以它不工作讓我編譯時錯誤斜面在類型之間轉換!

回答

1

這裏是我是如何實現它:

public class LambdaCriteries<T> : List<Expression<Func<T, bool>>> 
{ 
    public Expression<Func<T, bool>> GetFinalLambdaExpression() 
    { 
     var par = Expression.Parameter(typeof(T)); 
     var intial = Expression.Invoke(this.First(),par); 
     var sec = Expression.Invoke(this.Skip(1).First(),par); 
     BinaryExpression binaryExpression = Expression.And(intial, sec); 
     if (this.Count> 2) 
     { 
      foreach (var ex in this.ToList().Skip(2)) 
      { 
       binaryExpression = Expression.And(binaryExpression, Expression.Invoke(ex, par)); 
      } 
      return Expression.Lambda<Func<T, bool>>(binaryExpression,par); 
     } 
     else 
     { 
      return Expression.Lambda<Func<T, bool>>(binaryExpression,par); 
     } 

    } 
} 

,並使用它:

  if(txtId.text != "") 
       criteries.Add(v => v.Id == int.Parse(txtId.text)); 
      if(txtName.text != "") 
       criteries.Add(v => v.Name == txtId.text); 

,並最終表現:

var finalexp = criteries.GetFinalLambdaExpression(); 
2

,你可以創建這樣一些表述:

var a = c => c.name == txtName.Text; 
var b = c => c.name == txtName.Text; 

,然後將它們連接起來是這樣的:

var result = c => a(c) && b(c); 
+0

肯定的,但與問題是,我將失去智能感知並強烈鍵入我試過 var a =(Customer C)=> c.name == txtName.Text; 但它給了我編譯時錯誤: lambda表達式不能分配給隱式類型的局部變量 – Stacker 2010-08-10 08:45:43

+1

@Zeus那不是你的lambda表達式的錯誤,但只是specifiing你正在尋找的委託類型的要求在你的情況下創建你可以propably寫Predicate 或Func 。沒有你不會放鬆類型安全。 _只是鬆動那是動態的。 – 2010-08-10 08:54:59

2

像這樣:

Func<Customer, bool> predicate = c => true; 

if (txtName.Text.Trim() != "") 
    predicate = Concatenate(predicate, c => c.Name == txtName.text); 
if (txtEmail.Text.Trim() != "") 
    predicate = Concatenate(predicate, c => c.Email == txtEmail.text); 



static Func<T, bool> Concatenate(Func<T, bool> a, Func<T, bool> b) { 
    return t => a(t) && b(t); 
} 

Concatenate方法必須是一個獨立的方法因爲lambda表達式通過引用捕獲變量。

predicate = c => predicate(c) && c.Name == txtName.text; 

將導致堆棧溢出,因爲predicate變量總是引用您分配給它的最新一成不變的委託實例。

+1

爲什麼會導致堆棧溢出委託是不可變的,因此我期望RHS上的謂詞可以引用與分配給LHS的不同對象 – 2010-08-10 08:57:35

+0

@Rune:lambda將通過引用對變量進行fcpature。當它調用'predicate(c)'時,'predicate'變量將引用變量中的_current_ immutable委託實例,這是調用的lambda表達式。請刪除您的downvote。 – SLaks 2010-08-10 09:02:49

+0

我沒有downvoted – 2010-08-10 09:09:21

2
return Customers.Where(c => (txtName.Text.Trim() == "" || c.Name == txtName.Text) 
         && (txtEmail.Text.Trim() == "" || c.Email == txtEmail.Text)); 

換句話說,只處以「名稱」狀態,如果「名」盒子裏裝滿了,並且僅在「電子郵件」框中填寫徵收「電子郵件」的條件。

請注意,您可以使用.NET 4.0中的String.IsNullOrWhiteSpace方法,而不是您已使用的修剪技術。