我正在构建一个表单来显示一个列表,该列表将根据我的WinForm应用程序中的用户条件进行过滤,
假设我有一个通用列表IList<Order>
和Order
有一些属性,如OrderId
,CustomerName
,CreationDate
,...
public Class Order
{
public string OrderId {get; set;}
public string CustomerName {get; set;}
public DateTime CreationDate {get; set;}
}
另外,我在表单中添加了一些控件可以过滤列表。一个TextBox
OrderId
另一个CustomerName
和DateTimePickers
CreationDate
范围(FromDateTimePicker,ToDateTimePicker)。
我也将谓词变量定义为:
Func<Order, bool> predicate = null;
现在如何根据用户输入值构建我的predicate
?
我试着写这段代码:
if (tbOrderId.Text != string.Empty)
{
string orderId;
predicate = t=>t.OrderId == orderId;
}
if(tbCustomerName.Text != string.Empty)
{
string customer = tbCustomerName.Text;
if(predicate!=null)
predicate = predicate && (t=>t.CustomerName == customer);
else
predicate = (t=>t.CustomerName == customer);
}
....
但是我收到了这个错误:
Operator '&&' cannot be applied to operands of type 'System.Func<Order,bool>' and 'lambda expression'
答案 0 :(得分:2)
您的代码无效,因为您实际上并未将&&
应用于谓词的结果,而是将其应用于谓词本身。即使你是这样写的:
predicate = t => predicate(t) && t.CustomerName == customer;
它会编译,但你最终会得到无限递归。
为简单起见,您可以使用纯Linq(可以使用任何IEnumerable<T>
)来执行此操作:
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);
}
或者使用表达式(适用于IQueryable<T>
):
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);