代码改变世界

一个动态构建 LambdaExpression Tree 的示例

2019-07-25 15:55  音乐让我说  阅读(177)  评论(0)    收藏  举报

直接贴代码了:

    public class ExpressionTreeBuildingSampleTwo : Sample
    {
        public override string Name { get; } = "Building Expression Trees, Sample 2: Building Loops and Conditionals";
        
        public override void Run()
        {
            // This code builds the equivalent of:
            Func<int, int> factorialFunc = (n) =>
            {
                var res = 1;
                while (n > 1)
                {
                    res = res * n;
                    n--;
                }
                return res;
            };

            var nArgument = Expression.Parameter(typeof(int), "n");
            //Expression.Parameter (可能是声明参数的操作) :  int n;
            // A=Expression.Parameter 和 B=Expression.Variable 区别可能是:A是委托的传入参数,B是方法体内的局部变量。
            var result = Expression.Variable(typeof(int), "result"); // int result;

            // Creating a label that represents the return value
            LabelTarget label = Expression.Label(typeof(int)); //Expression.Label (可能是声明返回值操作) : return result

            var initializeResult = Expression.Assign(result, Expression.Constant(1));//Expression.Assign (赋值操作) :  {(result = 1)}

            // This is the inner block that performs the multiplication,
            // and decrements the value of 'n'
            var block = Expression.Block(
                Expression.Assign(result, // Expression.Assign (赋值操作) : result = result * n
                    Expression.Multiply(result, nArgument)), //Expression.Multiply (变量乘[*]操作) : result * n
                Expression.PostDecrementAssign(nArgument) // /Expression.PostDecrementAssign (变量减减[--]操作) :  {(n--)}
            ); //最终呈现如下:
            /*
             
                {
                    result = result * n;
                    n--;
                }
             
             */

            BinaryExpression nGreaterThanOneExpression = Expression.GreaterThan(nArgument, Expression.Constant(1));
            // Expression.GreaterThan (大于操作) : n > 1

            //public static ConditionalExpression IfThenElse(Expression test, Expression ifTrue, Expression ifFalse)
            var loopBodyExpression = Expression.IfThenElse( 
                        nGreaterThanOneExpression, // n > 1
                        block, // { result = result * n;  n--; }
                        Expression.Break(label, result)
                    );
            //上面大概最终呈现:
            /*
            if(n > 1) 
            {
                {
                    result = result * n;
                    n--;
                }
            }
            else
            {
                break
            }
             
             */

            LoopExpression loopExpression = Expression.Loop(loopBodyExpression, label);
            // Expression.Loop (循环操作) : 

            // Creating a method body.
            // public static BlockExpression Block(IEnumerable<ParameterExpression> variables, params Expression[] expressions)
            BlockExpression body = Expression.Block(
                new[] { result }, /* IEnumerable<ParameterExpression> variables */
                initializeResult, /* Expression 1   (   { int result = 1}   ) */
                loopExpression
            /* Expression 2  */
            /*

                    while (n > 1)
                    {
                        res = res * n;
                        n--;
                    }
                    return res;

             */
            );

            var factorial = Expression.Lambda(body, nArgument);

            // Compile and run an expression tree.
            var func = (Func<int, int>)factorial.Compile();

            Console.WriteLine(func(5));
            var visitor = Visitor.CreateFromExpression(factorial);
            visitor.Visit("");
       }
    }

 

谢谢浏览!