C# 根据用户选择在运行时构建动态谓词

C# 根据用户选择在运行时构建动态谓词,c#,dynamic,lambda,runtime,C#,Dynamic,Lambda,Runtime,我正在构建一个表单,以显示将根据WinForm应用程序中的用户条件进行筛选的列表, 假设我有一个通用列表IList和Order 具有一些属性,例如OrderId,CustomerName,CreationDate public Class Order { public string OrderId {get; set;} public string CustomerName {get; set;} public DateTime CreationDate {get; set;} } 此外

我正在构建一个表单,以显示将根据WinForm应用程序中的用户条件进行筛选的列表, 假设我有一个通用列表
IList
Order
具有一些属性,例如
OrderId
CustomerName
CreationDate

public Class Order
{
 public string OrderId {get; set;}
 public string CustomerName {get; set;}
 public DateTime CreationDate {get; set;}
}
此外,我在表单中添加了一些控件,以便用户可以筛选列表。一个
文本框
用于
订单ID
另一个用于
客户名称
和两个
日期时间选择器
用于
创建日期
范围(从日期时间选择器到日期时间选择器)

我还将谓词变量定义为:

Func<Order, bool> predicate = null; 
但我得到了这个错误:

Operator '&&' cannot be applied to operands of type 'System.Func<Order,bool>' and 'lambda expression'
运算符“&&”不能应用于“System.Func”和“lambda expression”类型的操作数

您的代码不起作用,因为您实际上并没有将
&&
应用于谓词的结果,而是将其应用于谓词本身。即使你这样写:

predicate = t => predicate(t) && t.CustomerName == customer;
它可以编译,但最终会得到无限递归

为了简单起见,您可以使用纯Linq(将与任何
IEnumerable
一起使用)简单地执行此操作:

predicate = t => predicate(t) && t.CustomerName == customer;
IEnumerable<Order> results = ... // all items

if (tbOrderId.Text != string.Empty)
{
   string orderId;
   results = results.Where(t => t.OrderId == orderId);
}

if (tbCustomerName.Text != string.Empty)
{
   string orderId;
   results = results.Where(t => t.CustomerName == customer);
}
ParameterExpression parameter = Expression.Parameter(typeof(DateTime));
Expression predicate = Expression.Constant(true);

if (tbOrderId.Text != string.Empty)
{
   string orderId = tbOrderId.Text;
   Expression prop = Expression.PropertyOrField(parameter, "OrderId");
   Expression filter = Expression.Equal(prop, Expression.Constant(orderId));
   predicate = Expression.AndAlso(predicate, filter);
}

if(tbCustomerName.Text != string.Empty)
{
   string customer = tbCustomerName.Text;
   Expression prop = Expression.PropertyOrField(parameter, "CustomerName");
   Expression filter = Expression.Equal(prop, Expression.Constant(customer))
   predicate = Expression.AndAlso(predicate, filter);
}

Expression lambda = Expression.Lambda(predicate, parameter);
return results.Where(lambda);