2010-08-10 125 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方法,而不是您已使用的修剪技术。