我关注了这个线程:link text
杰森举了一个例子:
public static Expression<TDelegate> AndAlso<TDelegate>(this Expression<TDelegate> left, Expression<TDelegate> right)
{
return Expression.Lambda<TDelegate>(Expression.AndAlso(left, right), left.Parameters);
}
及其用法:
Expression<Func<Client, bool>> clientWhere = c => true;
if (filterByClientFName)
{
clientWhere = clientWhere.AndAlso(c => c.ClientFName == searchForClientFName);
}
if (filterByClientLName)
{
clientWhere = clientWhere.AndAlso(c => c.ClientLName == searchForClientLName);
}
我有一个订单表,我按照上面的示例进行操作,更改了列名,并且得到了类似帖子创建者的错误
有人对我缺少的东西有任何想法吗?
更新:
埃里克(Eric),我进一步关注了上一篇文章的用户的询问,这里是link text
用户有这个
Expression<Func<Client, bool>> clientWhere = c => true;
Expression<Func<Order, bool>> orderWhere = o => true;
Expression<Func<Product, bool>> productWhere = p => true;
if (filterByClient)
{
clientWhere = c => c.ClientID == searchForClientID;
}
现在,如果他在
filterByClient
中具有各种条件,假设他要么拥有clientid
和/或其他某个列名,那将如何构建clientWhere
表达式? 最佳答案
您正在尝试构建一个表示以下内容的表达式树:
c => true && c.ClientFName == searchForClientFName
您实际上是在构建表示此的表达式树:
c => c=> true && c => c.ClientFName == searchForClientFName
这根本没有意义。
现在,您可能天真地认为这会起作用:
public static Expression<TDelegate> AndAlso<TDelegate>(this Expression<TDelegate> left, Expression<TDelegate> right)
{
// NOTICE: Combining BODIES:
return Expression.Lambda<TDelegate>(Expression.AndAlso(left.Body, right.Body), left.Parameters);
}
在您的情况下,这将代表
c => true && c.ClientFName == searchForClientFName
看起来不错。但是实际上这是脆弱的。假设你有
... d => d.City == "London" ...
... c => c.ClientName == "Fred Smith" ...
然后您使用此方法将它们组合在一起。你会得到一个代表
c => d.City == "London" && c.ClientName == "Fred Smith"
那里到底在做什么?
此外,参数是通过对象标识而不是参数名称来匹配的。如果你这样做
... c => c.City == "London" ...
... c => c.ClientName == "Fred Smith" ...
并组合成
c => c.City == "London" && c.ClientName == "Fred Smith"
你在同一条船上; “c.City”中的“c”与其他两个c不同。
您实际上需要做的是制作第三个参数对象,将其替换为两个lambda的主体中每个参数出现的位置,然后根据生成的替换主体构建新的lambda表达式树。
您可以通过编写访问者来构建替换引擎,该访问者越过表达式树主体,并随其进行重写。
关于c# - 附加到表达式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2231302/