表达式树:将 <variable> + 1 / <variable> -1 等表达式分别替换为递增/递减操作

Expression Tree: replace expressions like <variable> + 1 / <variable> -1 with increment / detriment operations respectively

我想用表达式树将 () => a - 1 + b + 1 lambda 转换成类似 () => a-- + b++ 的东西。

我实现了继承自 ExpressionVisitor.cs 的 class ExpressionTreeTransformer.cs 并覆盖了 VisitBinary 方法:

protected override Expression VisitBinary(BinaryExpression node)
        {
            if (!TryGetNumberValueFromExpressionNode(node.Left, out var leftNodeValue))
            {
                return base.VisitBinary(node);
            }

            if (!TryGetNumberValueFromExpressionNode(node.Right, out var rightNodeValue) || rightNodeValue != 1)
            {
                return base.VisitBinary(node);
            }

            var resultedExpression = node.NodeType switch
            {
                ExpressionType.Add => Expression.Increment(Expression.Constant(leftNodeValue)),
                ExpressionType.Subtract => Expression.Decrement(Expression.Constant(leftNodeValue)),
                _ => base.VisitBinary(node)
            };

            return resultedExpression;
        }

如果像 () => (a - 1) + (b + 1) 这样应用括号,它工作正常,但如果我们尝试 () => a - 1 + b + 1

经过一些调查,我发现这是表达式树构建节点的方式的原因。 没有括号的步骤如下:

  1. 左(a - 1) + 右(b)
  2. 左(1 步的结果)+ 右(1)

表达式节点在处理程序链中处理:

_expressionHandlers = new MemberExpressionHandler();
_expressionHandlers.SetSuccessor(new ConstantExpressionHandler());

变量处理程序:

public class MemberExpressionHandler : AbstractTreeExpressionHandler
    {
        public override bool Handle(Expression expressionNode, out int nodeValue)
        {
            if (expressionNode is MemberExpression memberExpression)
            {
                var constantExpression = memberExpression.Expression as ConstantExpression;
                var field = (FieldInfo)memberExpression.Member;

                if (constantExpression != null)
                {
                    var value = field.GetValue(constantExpression.Value);
                    var isNumber = int.TryParse(value.ToString(), out nodeValue);

                    if (isNumber)
                    {
                        return true;
                    }
                }
            }
            else
            {
                if (_successor != null)
                {
                    return _successor.Handle(expressionNode, out nodeValue);
                }
            }

            nodeValue = 0;

            return false;
        }
    }

常量处理程序:

public class ConstantExpressionHandler : AbstractTreeExpressionHandler
    {
        public override bool Handle(Expression expressionNode, out int nodeValue)
        {
            var isConstant = expressionNode is ConstantExpression;
            var isNumber = int.TryParse(((ConstantExpression)expressionNode).Value.ToString(), out nodeValue);

            if (isConstant && isNumber)
            {
                return true;
            }

            return false;
        }
    }

问:我被卡住了,请分享您如何正确解决此任务的经验

P.s 结果:

我认为当您找到 1 的常数加法或减法时,您需要检查左侧并确定是否可以将 addition/subtraction 提升为 increment/decrement.这是我的示例代码:

public class UnaryConstant1 : ExpressionVisitor {
    protected override Expression VisitBinary(BinaryExpression node) {
        if (node.Right is ConstantExpression c && c.Type.IsNumeric() && (Int32)c.Value == 1) {
            if (node.NodeType == ExpressionType.Add || node.NodeType == ExpressionType.Subtract) {
                if (node.Left is MemberExpression) {
                    if (node.NodeType == ExpressionType.Add)
                        return Expression.Increment(node.Left);
                    else
                        return Expression.Decrement(node.Left);
                }
                else if (node.Left is BinaryExpression left && (left.NodeType == ExpressionType.Add || left.NodeType == ExpressionType.Subtract)) {
                    Expression right;
                    if (node.NodeType == ExpressionType.Add)
                        right = Expression.Increment(left.Right);
                    else
                        right = Expression.Decrement(left.Right);

                    if (left.NodeType == ExpressionType.Add)
                        return Expression.Add(Visit(left.Left), right);
                    else
                        return Expression.Subtract(Visit(left.Left), right);
                }
            }
        }
        return base.VisitBinary(node);
    }
}