C# 动态构建 lambda 表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/904296/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:27:26  来源:igfitidea点击:

Dynamic build lambda expressions

c#lambda

提问by Henrik P. Hessel

So, I started to build a small test application to test lambda expressions. I found several examples here and elsewhere but I just don't get them.

因此,我开始构建一个小型测试应用程序来测试 lambda 表达式。我在这里和其他地方找到了几个例子,但我就是不明白。

Can anybody explain my how to build an expression by using textboxes or any other variables?

任何人都可以解释我如何使用文本框或任何其他变量来构建表达式吗?

My Test List

我的测试清单

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

Working lambda Expression

工作 lambda 表达式

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

How can I build the expressions dynamically?

如何动态构建表达式?

Something like lPeople.Where(p => p.LastName == Textbox.Text);(which of course doesn't work)

类似的东西lPeople.Where(p => p.LastName == Textbox.Text);(这当然不起作用)

Thanks!

谢谢!

Edit: Added some code to the solution below

编辑:在下面的解决方案中添加了一些代码

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

采纳答案by Daniel Earwicker

"which of course doesn't work"

“这当然行不通”

What happens when you try it? By the look of it, that's the kind of thing I do all the time.

当你尝试时会发生什么?看样子,这就是我一直在做的事情。

To switch operations based on a ComboBox specifying the operator:

要根据指定运算符的 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();

The code that converts the age string into an intwill throw if the user enters something that can't be converted. Look up TryParseto avoid exceptions.

int如果用户输入了无法转换的内容,则将年龄字符串转换为 an 的代码将抛出。查找TryParse以避免异常。

回答by Robert Harvey

You can use the Linq Dynamic Query Library to accomplish this. See the following blog post from Scott Guthrie for more information:

您可以使用 Linq 动态查询库来完成此操作。有关更多信息,请参阅 Scott Guthrie 的以下博客文章:

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

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

回答by Sudhir Jonathan

Try the Predicate Builder at http://www.albahari.com/nutshell/predicatebuilder.aspx

http://www.albahari.com/nutshell/predicatebuilder.aspx试试 Predicate Builder

I used it to make an advanced search where the user could keep adding optional search criteria.

我用它来进行高级搜索,用户可以在其中不断添加可选的搜索条件。

回答by Jason

Your example lambda expression will work. How dynamic do you need it to be? If you have a static UI of 'filters' to apply to a collection, you can create code similar to the following:

您的示例 lambda 表达式将起作用。你需要它有多动态?如果您有一个“过滤器”的静态 UI 应用于集合,您可以创建类似于以下内容的代码:

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

If you want the consumer of your data source to apply truly dynamic expressions (afford them the ability to choose other fields to filter and the expressions to use), that's a more complicated feature to implement using a predicate builder tool or LINQ Expression objects.

如果您希望数据源的使用者应用真正的动态表达式(让他们能够选择要过滤的其他字段和要使用的表达式),那么使用谓词构建器工具或 LINQ 表达式对象来实现这是一个更复杂的功能。

回答by John Rasch

There should be nothing wrong with the way you're going about it. I have created a simple Windows Forms Application with a TextBox, a Button, and a DataGridView(with names textBox1, button1, and dgv_1respectively.)

你这样做的方式应该没有问题。我创建了一个简单的Windows窗体应用程序TextBox,一Button,和DataGridView(同名称textBox1button1dgv_1分别。)

Here is the code I used for the Form1.csfile that worked as expected:

这是我用于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; }
}

回答by g1ga

In case of dynamic user choice, I think that a more elegant solution rather then using if blocks would be to declare a variable

在动态用户选择的情况下,我认为比使用 if 块更优雅的解决方案是声明一个变量

Func<People, bool> expFilter;

set its value based upon the user choice

根据用户选择设置其值

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

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

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

and then pass it to the Where clause:

然后将其传递给 Where 子句:

result = lPeople.Where(expFilter);