Лямбда-выражения и поиск - PullRequest
       5

Лямбда-выражения и поиск

4 голосов
/ 10 августа 2010

Допустим, у меня есть форма, которая имеет следующее:

Имя: TextBox
E-mail: TextBox
Возраст: TextBox

Теперь я хочу получить коллекцию клиентов на основе этого фильтра.

так что я хочу использовать что-то вроде:

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;

как мне это сделать! я не могу объединить лямбда-выражения, я знаю, что могу использовать динамические выражения, но я думаю, что есть более простой способ? Есть идеи, как это реализовать?


хорошо, я попробовал это:

        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, ожидает Expression<Func<T, bool>> expression

, так что это не работает, дает мне ошибку времени компиляции, я не могу конвертировать между типами!

Ответы [ 4 ]

2 голосов
/ 10 августа 2010

Как это:

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 должен быть отдельным методом, поскольку лямбда-выражения захватывают переменные по ссылке.

Линия

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

приведет к переполнению стека, поскольку переменная predicate всегда будет ссылаться на последний неизменяемый экземпляр делегата, который вы ему назначите.

2 голосов
/ 10 августа 2010
return Customers.Where(c => (txtName.Text.Trim() == "" || c.Name == txtName.Text)
                      && (txtEmail.Text.Trim() == "" || c.Email == txtEmail.Text));

Другими словами, накладывайте условие «имя», только если заполнено поле «имя», и только условие «электронная почта», если заполнено поле «адрес электронной почты».

Обратите внимание, что вы можете использовать метод String.IsNullOrWhiteSpace в .NET 4.0 вместо использованной вами техники обрезки.

2 голосов
/ 10 августа 2010

Вы можете создать несколько выражений, таких как:

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

, а затем объединить их следующим образом:

var result = c => a(c) && b(c);
1 голос
/ 15 августа 2010

Вот как я это реализовал:

   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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...