Imprima la jerarquía del árbol de expresiones de Linq

dynamic-language-runtime expression-trees linq string

Pregunta

El lenguaje dinámico runtime (DLR) tiene un código bastante bueno para Expression, que incluye un código muy bueno para imprimir los árboles de Expresión que quiero usar para que:

int a = 1;
int b = 2;
Expression<Func<int, int>> expression = (c) => a + (b * c)
expression.Evaluate(5, stringBuilder)

Salidas:

(5) => a + (b * c) = 11 Where
     a = 1
     b * c = 10 Where
          b = 2
          c = 5

Encontré algo de código en la red para hacer esto, pero encontré que solo funciona si la expresión no toma ningún argumento.

http://incrediblejourneysintotheknown.blogspot.com/2009/02/displaying-nested-evaluation-tree-from.html

Entonces descubrí la implementación DLR de un método similar. Sin embargo, el DLR tiene sus propias implementaciones personalizadas de la clase Expression y muchos otros tipos estándar de C #, así que me confundí un poco. Alguien sabe como puedo implementar lo anterior?

Respuesta experta

Qué tal si:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;

static class Program
{
    static void Main()
    {
        int a = 1, b = 2;
        StringBuilder sb = new StringBuilder();
        Expression<Func<int, int>> expression = (c) => a + (b * c);
        expression.Evaluate(sb, 5);
        // now fix the capture class names (from a and b)
        string s = sb.ToString();
        s = Regex.Replace(s, @"value\([^)]+\)\.", "");
        Console.WriteLine(s);
    }
    public static void Evaluate(this LambdaExpression expr, StringBuilder builder, params object[] args)
    {
        var parameters = expr.Parameters.ToArray();
        if (args == null || parameters.Length != args.Length) throw new ArgumentException("args");
        Evaluate(expr.Body, 0, builder, parameters, args);
    }
    private static StringBuilder Indent(this StringBuilder builder, int depth)
    {
        for (int i = 0; i < depth; i++) builder.Append("  ");
        return builder;
    }
    private static void Evaluate(this Expression expr, int depth, StringBuilder builder, ParameterExpression[] parameters, object[] args)
    {
        builder.Indent(depth).Append(expr).Append(" = ").Append(Expression.Lambda(expr, parameters).Compile().DynamicInvoke(args));

        UnaryExpression ue;
        BinaryExpression be;
        ConditionalExpression ce;

        if ((ue = expr as UnaryExpression) != null)
        {
            builder.AppendLine(" where");
            Evaluate(ue.Operand, depth + 1, builder, parameters, args);
        }
        if ((be = expr as BinaryExpression) != null)
        {
            builder.AppendLine(" where");
            Evaluate(be.Left, depth + 1, builder, parameters, args);
            Evaluate(be.Right, depth + 1, builder, parameters, args);                   
        }
        else if ((ce = expr as ConditionalExpression) != null)
        {
            builder.AppendLine(" where");
            Evaluate(ce.Test, depth + 1, builder, parameters, args);
            Evaluate(ce.IfTrue, depth + 1, builder, parameters, args);
            Evaluate(ce.IfFalse, depth + 1, builder, parameters, args);
        }
        else
        {
            builder.AppendLine();
        }
    }

}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow