C # expression trees using dynamic method invocation and achieve 99 multiplication table

When we use the C # programming, often using reflection to dynamically invoke methods, but sometimes requires dynamic generation method, here are ways to use the expression tree method to automatically generate and call.

We first need to explain what is an expression familiar with Linq program apes have used similar to the following code: t => t.Length <= 25;

In C # => This is a representative of Lambda expressions, which is used for the array to query, statistics, sort, de-duplication feature is very useful. The expression tree is to implement related functions by dynamically creating a Lambda way.

The following is an example of the apply function similar to JS.

The use of the expression tree, be sure to quote System.Linq.Expressions; one of the Expression class there are many ways to define a method for everything needed.

public class CommonTest

    {

        public object TestMethodCall(int age, string name)

        {

            Console.WriteLine($"{name}'s Age is {age}");

            return true;

        }

        public object TestExpression(MethodInfo method, object[] parameters, CommonTest instance)

        {

            // finally generated expression style (m, p) => {return (object) m.method (p);}

            // define two parameter expressions

            ParameterExpression mParameter = Expression.Parameter (typeof (CommonTest), "m"); // Define a name for the parameter m

            ParameterExpression pParameter = Expression.Parameter (typeof (object []), "p"); // Define a name for the parameter p

 

            ParameterInfo [] tParameter = method.GetParameters (); // process the acquired all the parameters

            Expression [] rParameter = new Expression [tParameter.Length]; // definition of the same and a method parameter container length expression, as in the method call is the need to use an expression, not directly use parameter list

            for (int i = 0; i < rParameter.Length; i++)

            {

                BinaryExpression pExpression = Expression.ArrayIndex (pParameter, Expression.Constant (i)); // acquired from the process to the corresponding parameter index

                UnaryExpression uExpression = Expression.Convert (pExpression, tParameter [i] .ParameterType); // this parameter type is converted to the actual parameters of the type

                rParameter [i] = uExpression; // Add the parameter corresponding to the parameter expression expression container

            }

 

            MethodCallExpression mcExpression = Expression.Call (mParameter, method, rParameter); // call the method, since it is the first example of the method must be a parameter m, if the method is static, then the first parameter should be null

            UnaryExpression reExpression = Expression.Convert (mcExpression, typeof (object)); // converts the result to object, because the dynamic method call to all, so the return value must be an Object, if the method returns no value, then no this step

            return Expression.Lambda <Func <CommonTest, object [], object >> (reExpression, mParameter, pParameter) .Compile () (instance, parameters); // be compiled into a method Func delegate, and execute him

        }

}

Called the above code as follows:

  CommonTest ct = new CommonTest();

            MethodInfo mi = typeof(CommonTest).GetMethod("TestMethodCall");

            var r = ct.TestExpression(mi, new object[] { 25, "SC" }, ct);

This method is also called in C # MVC controller Action principles of the code, its biggest role is to target no matter how many arguments Action has finally calls require only one object [] parameters, avoiding the direct use reflection to call, but uncertain number of difficult parameters.

Expression can not only use code similar to the above practice the principles of MVC, can also be an expression tree parsing can be achieved ORM Sql underlying structure, but this is no longer carried out explain, are interested can Baidu query parsing expression trees.

The disadvantage is the function expression tree implementation of complex, difficult to debug, suggestions before implementing first need to implement the use of C # syntax written out, then in accordance with the corresponding format is achieved by the expression tree, so relatively simple.

The following expression using the output of a multiplication table 99.

Here are the results achieved

 

 

 

The first is achieved by normal manner, as follows:

for (int i = 1; i <= 9; i++)

            {

                for (int j = 1; j <= i; j++)

                {

                    int total = i * j;

                    Console.Write($"{i} * {j} = {total}\t");

                }

                Console.WriteLine();

            }

            Console.ReadKey();

Here is the code expression tree achieve the same functionality:

/// <summary>

        /// using expression trees to achieve 99 multiplication table

        /// </summary>

        public void TestMultiple()

        {

            LabelTarget labOut = Expression.Label (); // bounce flag for external circulation

            LabelTarget labIn = Expression.Label (); // for out of the inner loop flag

 

            ParameterExpression iParameter = Expression.Parameter (typeof (int), "i"); // external circulation of the defined variables, like int i;

            ParameterExpression jParameter = Expression.Parameter (typeof (int), "j"); // definition of internal loop variables like int j;

            ParameterExpression rParameter = Expression.Parameter (typeof (int), "result"); // save the definition of the results for the variable i * j

 

            MethodInfo writeString = typeof(Console).GetMethod("Write", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null);//获取Write方法

            MethodInfo writeInt = typeof(Console).GetMethod("Write", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(int) }, null);//获取Write方法

 

            Expression expResult = Expression.Block(

                new [] {parameter, parameters, parameters},

                Expression.Assign (iParameter, Expression.Constant (1)), // i is the initial value assigned, similar to i = 1;

                Expression.Loop (Expression.Block (// Start the outer loop, the expression can only be achieved while loop, a for loop can not be achieved

                Expression.IfThenElse (Expression.LessThanOrEqual (iParameter, Expression.Constant (9)), // definition of conditional execution, similar to if (i <= 9) {

                                                                                                     // if the outside is true when the following code is executed

                  Expression.Block(

                    Expression.Assign (jParameter, Expression.Constant (1)), // initial value assigned to j, similar to j = 1;

                    Expression.Loop (Expression.Block (// inner loop starts here

                        Expression.IfThenElse (Expression.LessThanOrEqual (jParameter, iParameter), // definition of conditional execution, similar to if (j <= i) {

                                                                                                 // if the interior is true when the following code execution

                        Expression.Block(

                            Expression.Assign (rParameter, Expression.Multiply (iParameter, jParameter)), // where i * j for the result of the calculation and assignment, similar result = i * j

                                                                                                       // print out the results, similar to Console.Write ( "i * j =" + result + "\ t")

                            Expression.Call(null, writeInt, jParameter),

                            Expression.Call(null, writeString, Expression.Constant(" * ")),

                            Expression.Call(null, writeInt, iParameter),

                            Expression.Call(null, writeString, Expression.Constant(" = ")),

                            Expression.Call(null, writeInt, rParameter),

                            Expression.Call(null, writeString, Expression.Constant("\t")),

                            Expression.PostIncrementAssign (jParameter) // j self-growth, similar to j ++

                            ),

                            // if the interior is false when the following code execution

                            Expression.Break (labIn)) // here out of the inner loop)

                        ), labIn),

                    Expression.Block(

                         Expression.Call (null, writeString, Expression.Constant ( "\ n")), // here to print a line break, similar to Console.WriteLine ();

                         Expression.PostIncrementAssign (iParameter)) // i self-growth, similar to i ++

                         )

                        // if the outside is false when the following code execution

                        , Expression.Break (labOut)) // here out of the outer loop

                ), LabOut));

            Expression.Lambda<Action>(expResult).Compile()();

        }

Code to achieve the same effect as the preceding two paragraphs, the expression tree can be seen that the same function of the complexity far beyond the ordinary manner, the normal line of code 10, the expression tree 42 with a full line of code was implemented.

Guess you like

Origin www.cnblogs.com/ckym/p/11627622.html