如何使用括号动态创建 "System.Linq.Expression" 表达式
How to create "System.Linq.Expression" expression dynamically with parentheses
我需要动态创建表达式。我的问题是如何在 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);
我可能漏掉了你的问题,但你不会这样做吗:
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)))
您的代码已经具有这些语义。当您使用您拥有的确切代码调用 ToString
时,您会得到:
(((a > 1) OrElse (b > 1)) AndAlso ((c > 1) OrElse (d > 1)))
不需要特定的表达式来表示括号;括号隐含在您编写表达式的方式中。在您的代码中,您将 Or
表达式传递给 And
表达式,因此 Or
表达式将被括起来。
您可以通过构建表达式树的方式来指定优先级。 &&
运算符通常优先于 ||
运算符,因此您的转换将应用于带括号的表达式。否则它只是:
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)))
只是为了扩展其他答案;括号是我们需要的,以防止我们用来描述方程式 (A OP B) 的 infix 符号变得模棱两可。其他符号,例如 postfix (A B OP),不需要它。
在您的情况下,您正在组合一个表达式树,这也是明确的,即只有一种解释它的方法。所以表达式树中没有括号的概念。树的 "shape" 决定了操作顺序。
我需要动态创建表达式。我的问题是如何在 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);
我可能漏掉了你的问题,但你不会这样做吗:
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)))
您的代码已经具有这些语义。当您使用您拥有的确切代码调用 ToString
时,您会得到:
(((a > 1) OrElse (b > 1)) AndAlso ((c > 1) OrElse (d > 1)))
不需要特定的表达式来表示括号;括号隐含在您编写表达式的方式中。在您的代码中,您将 Or
表达式传递给 And
表达式,因此 Or
表达式将被括起来。
您可以通过构建表达式树的方式来指定优先级。 &&
运算符通常优先于 ||
运算符,因此您的转换将应用于带括号的表达式。否则它只是:
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)))
只是为了扩展其他答案;括号是我们需要的,以防止我们用来描述方程式 (A OP B) 的 infix 符号变得模棱两可。其他符号,例如 postfix (A B OP),不需要它。
在您的情况下,您正在组合一个表达式树,这也是明确的,即只有一种解释它的方法。所以表达式树中没有括号的概念。树的 "shape" 决定了操作顺序。