C # Knowledge review-expression tree Expressions Trees
Directory
- Brief introduction
- Lambda expressions Create an expression tree
- API to create an expression tree
- Parsing an expression tree
- Persistence of expression trees
- Compiling an expression tree
- Executing an expression tree
- Modify an expression tree
- Debugging
Brief introduction
Expression trees represent code in a tree-like structure, where each node is an expression, such as a method call and a two-dollar operation such as X < Y.
You can edit and operate the code in an expression tree. This enables dynamic modification of executable code, execution of LINQ queries in different databases, and creation of dynamic queries.
Expression trees can also be used in the Dynamic Language runtime (DLR) to provide interoperability between dynamic languages and the. NET Framework.
A LAMBDA expression creates an expression tree
If a lambda expression is assigned to a variable of type expression<tdelegate>, the compiler can emit code to create an expression tree that represents the lambda expression.
The C # compiler can only generate an expression tree from an expression lambda (or a single-line lambda).
The following code example creates a representation lambda expression using the keyword expression:
1 expression<action<int>> actionexpression = n = Console.WriteLine (n); 2 expression<func<0; 3 expression<func<0;
Second, the API to create an expression tree
Creating an expression tree from the API requires the use of the expressions class
The following code example shows how to create a representation lambda expression from the API: num = num = = 0
1//Creating an expression tree from an expression class2//lambda:num = num = 03 ParameterExpression pexpression = Expression.parameter (typeofint)); //4 ConstantExpression cexpression = expression.constant (0); // constant: 05 binaryexpression Bexpression = Expression.makebinary (expressiontype.equal, pexpression, cexpression); // expression: num = = 06 expression <func<int, bool>> lambda = Expression.lambda <func<int, bool>> (Bexpression, pexpression ); //LAMBDA expression: num = num = = 0
The code is created using the static method of the Expression class.
Iii. Parsing Expression Trees
The following code example shows how to break down an expression tree that represents a lambda expression num-= num = 0.
1 expression<func<Intbool>> funcexpression = num = num = =0; 2 3 // start parsing 4 parameterexpression pexpression = funcexpression.parameters[0]; //lambda expression parameter 5 binaryexpression BODY = (binaryexpression) funcexpression.body; //lambda expression body: num = = 06 7 Console.WriteLine ($" parse: {Pexpression.name} = {body. Left} {body. NodeType} {body. Right}");
The expression tree permanent expression tree should have a permanent (string-like). This means that if you want to modify an expression tree, you must copy the expression tree and replace the nodes in it to create a new expression tree. You can use an expression tree visitor to traverse an existing expression tree. The seventh section describes how to modify an expression tree. V. Compiling an expression tree
The expression<tdelegate> type provides a Compile method to compile the code represented by an expression tree into an executable delegate.
1//Creating an expression tree2 expression<func<Stringint>> funcexpression = MSG-=Msg. Length;3 // expression tree compiled into delegates 4 var lambda = Funcexpression.compile (); 5 // invoke delegate 6 Console.WriteLine (Lambda (" hello, world! "7 8 // syntax simplification 9 Console.WriteLine (Funcexpression.compile () ( "hello, World!
Vi. Executing an expression tree
Execution of an expression tree may return a value, or it may perform only one operation (such as calling a method).
You can only execute an expression tree that represents a lambda expression. The expression tree that represents the lambda expression belongs to the LambdaExpression or expression<tdelegate> type. To execute these expression trees, you call the Compile method to create an executable delegate, and then call the delegate.
1Constint n =1;2Constint m =2;34//Expression tree to be executed5 Binaryexpression bexpression =Expression.add (Expression.constant (n), Expression.constant (m));6// Create a lambda expression 7 Expression<func<int>> funcexpression = expression.lambda<func<< Span style= "COLOR: #0000ff" >int>> (bexpression); 8 // compile lambda expression 9 func<< Span style= "COLOR: #0000ff" >int> func = Funcexpression.compile (); 10 11 // execute lambda Expression 12 Console.WriteLine ($ " {n} + {m} = {func ()}
Vii. Modifying an expression tree
The class inherits the ExpressionVisitor class, and the VisitBinary method is indirectly called by the Visit method to replace! =. The base class method constructs nodes that resemble the passed-in expression tree, but these nodes replace their subtree with the accessor-generated expression tree.
1InternalClassProgram2{3PrivateStaticvoid Main (String[] args)4{5 expression<func<Intbool>> funcexpression = num = num = =0;6 Console.WriteLine ($"Source: {funcexpression}");78var visitor =NewNotequalexpressionvisitor ();9var expression =Visitor. Visit (funcexpression);10Console.WriteLine ($"Modify: {expression}");1213Console.read ();14}1516///<summary>17///Unequal expression tree accessors18///</summary>19PublicClassNotequalexpressionvisitor:expressionvisitor20{21stPublicExpression Visit (binaryexpression node)22{23ReturnVisitBinary (node);24}2526 protected override< Span style= "COLOR: #000000" > Expression VisitBinary (binaryexpression node) 27 {28 return node. NodeType == Expressiontype.equal29? Expression.makebinary (expressiontype.notequal, node. Left, node. right) // re-get an expression: use! = instead of == : base31 }32 }33}
Eight, commissioning
8.1 Parameter Expressions
1 parameterexpression pExpression1 = Expression.parameter (typeof (string)); 2 parameterexpression pExpression2 = Expression.parameter (typeof ("msg");
Figure 8-1
Figure 8-2
From DebugView, if the parameter does not have a name, it is assigned an auto-generated name.
1 ; ; 4 ConstantExpression cExpression1 = expression.constant (NUM1); 5 ConstantExpression CExpression2 = Expression.constant (num2);
Figure 8-3
Figure 8-4
From DebugView, float has a suffix F more than int.
1 Expression lambda1 = expression.lambda<func<int>> (expression.constant ()); 2 Expression lambda2 = expression.lambda<func<int>> (expression.constant ("customname null);
Figure 8-5
Figure 8-6
Observing DebugView, if the lambda expression does not have a name, it is assigned an automatically generated name.
[C #] C # Knowledge review-expression tree Expressions Trees