Динамическое построение лямбда-выражений - PullRequest
4 голосов
/ 24 мая 2009

Итак, я начал создавать небольшое тестовое приложение для проверки лямбда-выражений. Я нашел несколько примеров здесь и в других местах, но я просто не понимаю их.

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

Мой список тестов

List<People> lPeople = new List<People> 
{
    new People { Name= "Jean", LastName = "Borrow", Age= 21 } ,
    new People { Name= "Dean", LastName = "Torrow", Age= 20 }
};

Рабочая лямбда-выражение

IEnumerable<People> result = lPeople.Where(p => p.Age < 21);
dgv_1.DataSource = result.ToList();
dgv_1.Update();

Как я могу построить выражения динамически?

Что-то вроде lPeople.Where(p => p.LastName == Textbox.Text); (что, конечно, не работает)

Спасибо!

Редактировать: добавлен код для решения ниже

Int32 iAge;
Boolean bSuc = Int32.TryParse(tb_filter_age.Text, out iAge);
if (!bSuc)
{
    iAge = 0;
}

Ответы [ 6 ]

5 голосов
/ 24 мая 2009

Попробуйте Построитель Предикатов на http://www.albahari.com/nutshell/predicatebuilder.aspx

Я использовал его для расширенного поиска, где пользователь мог добавлять дополнительные критерии поиска.

5 голосов
/ 24 мая 2009

"что, конечно, не работает"

Что происходит, когда вы пытаетесь это сделать? Судя по всему, это то, чем я занимаюсь все время.

Для переключения операций на основе ComboBox с указанием оператора:

int age = int.Parse(textBoxAge.Text);

IEnumerable<People> result;
if (comboBoxOperator.Text == "=")
    result = lPeople.Where(p => p.Age == age);
else if (comboBoxOperator.Text == "<")
    result = lPeople.Where(p => p.Age < age);
else
    result = lPeople.Where(p => p.Age > age);

dgv_1.DataSource = result.ToList();
dgv_1.Update();

Код, который преобразует строку возраста в int, будет выдан, если пользователь введет что-то, что не может быть преобразовано. Посмотрите вверх TryParse, чтобы избежать исключений.

2 голосов
/ 24 мая 2009

Не должно быть ничего плохого в том, как вы это делаете. Я создал простое приложение Windows Forms с TextBox, Button и DataGridView (с именами textBox1, button1 и dgv_1 соответственно.)

Вот код, который я использовал для файла Form1.cs, который работал как положено:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        List<People> lPeople = new List<People> 
        {
            new People { Name= "Jean", LastName = "Borrow", Age= 21 } ,
            new People { Name= "Dean", LastName = "Torrow", Age= 20 }
        };

        IEnumerable<People> result = lPeople.Where(p => p.Name == textBox1.Text);

        dgv_1.DataSource = result.ToList();
        dgv_1.Update();
    }
}    

public class People
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}
2 голосов
/ 24 мая 2009

Ваш пример лямбда-выражения будет работать. Насколько динамичным вам это нужно? Если у вас есть статический интерфейс «фильтров» для применения к коллекции, вы можете создать код, подобный следующему:

IEnumerable<People> result = lPeople;
if (txtLastName.Text.Trim().Length != 0) 
    result = result.Where(p => p.LastName == txtLastName.Text); 
if (chkSeniors.Checked) 
    result = result.Where(p => p.Age >= 65);
dgv_1.DataSource = result.ToList();
dgv_1.Update();

Если вы хотите, чтобы потребитель вашего источника данных применял действительно динамические выражения (предоставьте им возможность выбирать другие поля для фильтрации и используемые выражения), это более сложная функция для реализации с использованием инструмента построителя предикатов или выражения LINQ. объекты.

2 голосов
/ 24 мая 2009

Для этого вы можете использовать динамическую библиотеку запросов Linq. Смотрите следующую запись в блоге от Скотта Гатри для получения дополнительной информации:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

1 голос
/ 08 ноября 2011

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

Func<People, bool> expFilter;

установить его значение на основе выбора пользователя

switch(comboBoxOperator.Text)
{
   case "=":
   expFilter = p => p.Age == age;
   break;

   case ">":
   expFilter = p => p.Age > age;
   break;

   case "<":
   expFilter = p => p.Age < age;
   break;
}    

и затем передайте его предложению Where:

result = lPeople.Where(expFilter);        
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...