开发者

Lambda Expressions and searching

开发者 https://www.devze.com 2023-01-11 10:08 出处:网络
Lets say i have a form which have the following : Name:TextBox Email:TextBox Age:开发者_高级运维TextBox

Lets say i have a form which have the following :

Name:TextBox

Email:TextBox

Age:开发者_高级运维TextBox

now i want to Get customers Collection based on this filter textboxs

so i want to to use something like :

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

now of course i dont know which he will fill and which he wont so

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

how do i do this ! i cant concatenate lambda expressions , i know i can use dynamic expressions but i think there is easier way ? any idea how to implement this ?


ok i tried this:

        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);

now comes another problem

the method im passing CC to is expecting Expression<Func<T, bool>> expression

so it doesnt work gives me compile time error cant convert between types!


you can create some expressions like:

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

and then concatenate them like this:

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


Like this:

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

The Concatenate method must be a separate method because lambda expressions capture variables by reference.

The line

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

will result in a stack overflow because the predicate variable will always refer to the latest immutable delegate instance that you assign to it.


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

In other words, only impose the 'name' condition if the 'name' box is filled out, and only impose the 'email' condition if the 'email' box is filled out.

Note that you can use the String.IsNullOrWhiteSpace method in .NET 4.0 instead of the Trim technique you have used.


Here is how i Implemented it:

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

    }
}

and to use it :

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

and final expression :

var finalexp = criteries.GetFinalLambdaExpression();
0

精彩评论

暂无评论...
验证码 换一张
取 消