如何使用括号动态创建“System.Linq.Expression”表达式

本文关键字:Linq System Expression 表达式 创建 何使用 动态 | 更新日期: 2023-09-27 18:36:54

我需要动态创建表达式。我的问题是如何在System.Linq.Expression中添加括号来处理优先级...

int a = 1, b = 1, c = 1, d = 2;

我已经转换了下面的表达式

 var v = a > 1 || b > 1 && c > 1 || d > 1;
 Expression case1Expr =
                Expression.AndAlso(
                Expression.OrElse(
                Expression.GreaterThan(Expression.Parameter(typeof(int), "a"), Expression.Constant(1)),
                Expression.GreaterThan(Expression.Parameter(typeof(int), "b"), Expression.Constant(1))),

                Expression.OrElse(
                Expression.GreaterThan(Expression.Parameter(typeof(int), "c"), Expression.Constant(1)),
                Expression.GreaterThan(Expression.Parameter(typeof(int), "d"), Expression.Constant(1))));

但是如何转换一个带括号,

var v2 = (a > 1 || b > 1) && (c > 1 || d > 1);

如何使用括号动态创建“System.Linq.Expression”表达式

只是为了扩展一下其他答案; 括号是我们需要的,以防止我们用来描述方程(A OP B)的中缀符号模棱两可。其他表示法,如后缀 (A B OP),不需要它。

在你的例子中,你正在把一个表达式树放在一起,这也是明确的,即只有一种方法来解释它。因此,表达式树中没有括号的概念。树的"形状"决定了操作的顺序。

您可以通过构造表达式树的方式指定优先级。&&运算符通常优先于||运算符,因此您的转换将应用于带括号的表达式。否则,它只是:

var v = a > 1 || b > 1 && c > 1 || d > 1;
OrElse(
    GreaterThan(a > 1),
    OrElse(
      AndAlso(
        GreaterThan(b > 1),
        GreaterThan(c > 1)),
      GreaterThan(d > 1)))

您已经具有这些语义的代码。 当您调用ToString您拥有的确切代码时,您会得到以下内容:

(((a > 1) OrElse (b > 1)) AndAlso ((c > 1) OrElse (d > 1)))

不需要特定的表达式来表示括号;括号隐含在组成表达式的方式中。 在代码中,将Or表达式传递给And表达式,因此Or表达式将用括号括起来。

我可能会错过你的问题,但你不会这样做吗:

Expression first = Expression.OrElse(
    Expression.GreaterThan(Expression.Parameter(typeof(int), "a"), Expression.Constant(1)),
    Expression.GreaterThan(Expression.Parameter(typeof(int), "b"), Expression.Constant(1)));
Expression second = Expression.OrElse(
    Expression.GreaterThan(Expression.Parameter(typeof(int), "c"), Expression.Constant(1)),
    Expression.GreaterThan(Expression.Parameter(typeof(int), "d"), Expression.Constant(1)));
Expression final = Expression.AndAlso(first, second);

结果: (((a > 1) OrElse (b > 1)) AndAlso ((c > 1) OrElse (d > 1)))