我有两个Expression<Func<T, bool>>
类型的表达式,我想对它们进行OR、AND或NOT运算,得到一个相同类型的新表达式
Expression<Func<T, bool>> expr1;
Expression<Func<T, bool>> expr2;
...
//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2
9条答案
按热度按时间vqlkdk9b1#
嗯,你可以用
Expression.AndAlso
/OrElse
等来合并逻辑表达式,但问题是参数;您在expr 1和expr 2中使用的是相同的ParameterExpression
吗?如果是这样,则比较容易:这也适用于否定单个操作:
否则,根据LINQ提供程序的不同,您也许可以将它们与
Invoke
组合在一起:在某个地方,我有一些代码重写表达式树替换节点,以消除对
Invoke
的需要,但它相当长(我不记得我把它放在哪里了...)选择最简单路线的通用版本:
从.NET 4.0开始,有一个
ExpressionVisitor
类,它允许您构建EF安全的表达式。vuv7lop32#
你可以使用Expression. AndAlso/OrElse来组合逻辑表达式,但是你必须确保ParameterExpressions是相同的。
我在使用EF和PredicateBuilder时遇到了问题,所以我自己创建了一个,而没有求助于Invoke,我可以这样使用:
PredicateBuilder的源代码:
和实用程序类来替换lambda中的参数:
cbwuti443#
如果您的提供者不支援叫用,而您需要合并两个运算式,则可以使用ExpressionVisitor,以第一个运算式中的参数取代第二个运算式中的参数。
z0qdvdin4#
这里没有什么新的东西,只是将this answer与this answer结合起来,并对其进行了轻微的重构,这样即使是我也能理解发生了什么:
bnl4lu3b5#
我在这里结合了一些漂亮的答案,以便能够轻松支持更多的表达式运算符。
这是基于@Dejan的答案,但是现在添加OR也很容易。我选择不将
Combine
函数设置为public,但是您可以这样做以获得更大的灵活性。用法并没有改变,还是这样:
ct2axkht6#
我需要达到同样的结果,但使用更通用的东西(因为类型未知)。感谢marc的回答,我终于明白了我想要达到的目标:
wmomyfyw7#
我建议对 PredicateBuilder 和
ExpressionVisitor
解决方案再进行一次改进。我将其命名为UnifyParametersByName
,您可以在我的MIT库中找到它:LinqExprHelper。它允许组合任意的lambda表达式。通常问题是关于 predicate 表达式的,但这个想法也扩展到投影表达式。下面的代码使用了一个方法
ExprAdres
,该方法使用内联lambda创建了一个复杂的参数化表达式。由于LinqExprHelper
迷你库的存在,这个复杂的表达式只需编写一次,然后就可以重用了。下面是子表达式的构建代码:
我试图实现的是执行参数化查询,而不需要复制粘贴,并能够使用内联lambda,这是如此漂亮。如果没有所有这些助手表达式的东西,我将被迫创建整个查询一次。
myzjeezk8#
z18hc3ub9#
我觉得这样很好,不是吗?