What is an expression tree?
The Expression Tree, also known as the expression directory tree, represents the language level in the form of dataCode. All data is stored in the tree structure. Each node represents an expression ). To manually generate an Expression Tree, We need to reference the system. LINQ. Expressions namespace. The most important class is expression, which is the base class of all expressions. For example:
1: parameter expression: parameterexpression, which is a parameter in a method, such as search (string key). The key can be considered as a parameter expression.
2: Binary Expression: binaryexpression, such as A + B.
3: method call expression: methodcallexpression. For exampleProgramTo implement the orderby operation in:
Methodcallexpression orderbycallexpression = Expression. Call (
Typeof (Queryable ),
" Orderby " ,
New Type [] {queryabledata. elementtype, queryabledata. elementtype },
Wherecallexpression,
Expression. Lambda < Func < String , String > (PE, New Parameterexpression [] {PE }));
4: constant expression: constantexpression, for example, value 5.
5: field or attribute expression: memberexpression, for example, str. length. Expression. Property (PE, typeof (string). getproperty ("length "));
6: conditional expression: conditionalexpression.
7. Description Lambda expression: lambdaexpression
8: unaryexpression
9: related operation between expression and type: typebinaryexpression
And so on. They all inherit the expression.
Generic delegation:
The Expression Tree is often used with generic delegation. Here we will briefly introduce what a generic delegation is. Func <(of <(T, tresult>) Generic delegate: encapsulate a method that has a parameter and returns the type value specified by the tresult parameter. If you want to add parameters, you can write them as func <(of <(T1, T2, tresult>. This method is much simpler than the traditional method of displaying the Declaration delegate in terms of code structure. We do not need to apply for a delegate. All the delegates can be replaced by generic delegation. Here we simply implement an arithmetic expression to illustrate the benefits of generic delegation.
Arithmetic expression: (A + B) ^ B
1: The traditional display declarative delegation method.
1) declare a Commission:
/// <Summary>
/// (A + B) ^ B delegate
/// </Summary>
/// <Param name = "num_1"> Para 1 </Param>
/// <Param name = "num_2"> Para 2 </Param>
/// <Returns> </returns>
Public Delegate Double Powercompute ( Double Num_1, Double Num_2 );
2): The method body corresponding to the encoding delegate
/// <Summary>
/// (A + B) ^ B Method
/// </Summary>
/// <Param name = "num_1"> Para 1 </Param>
/// <Param name = "num_2"> Para 2 </Param>
/// <Returns> </returns>
Public Static Double Getpowercompute ( Double Num_1, Double Num_2)
{
Return Math. Pow (num_1 + Num_2), num_2 );
}
3): call:
Double Dresult = 0 ;
Powercompute PC = Getpowercompute;
Dresult = PC ( 2 , 2 );
Console. writeline (dresult. tostring ());
2: generic delegation implementation:
1): The method body corresponding to the encoding delegate. The method is the second step in the code above.
2): Call
Func < Double , Double , Double > FC = Getpowercompute;
Dresult = FC ( 2 , 2 );
Console. writeline (dresult. tostring ());
Execution of Expression Tree:
Expression Tree and generic delegate: here we implement a simple expression tree to implement (a + B) ^ B. In the process, we need to know the following three important methods.
1:Expression <(of <(tdelegate>): A strong Lambda expression is represented as a data structure in the form of an expression directory tree.
2:Expression. LAMBDA Method: Create an expression directory tree that represents a Lambda expression.
3:Expression <(of <(tdelegate>). Compile: Compile the lambda expression described in the expression directory tree into executable code.
The following is a (a + B) ^ B expression tree to generate code that can be executed and called on the client:
Parameterexpression penum_1 = Expression. parameter ( Typeof ( Double ), " Num_1 " );
Parameterexpression penum_2 = Expression. parameter ( Typeof ( Double ), " Num_2 " );
Binaryexpression _ be = Expression. Add (penum_1, penum_2 );
Binaryexpression _ Be2 = Expression. Power (_ be, penum_2 );
Expression < Func < Double , Double , Double > EF = Expression. Lambda < Func < Double , Double , Double > (_ Be2, New Parameterexpression [] {
Penum_1, penum_2 });
Func<Double,Double,Double>Cf=Ef. Compile ();
ReturnCF (num_1, num_2 );
The following is the relationship diagram of the Expression Tree (a + B) ^ B.
Modify the Expression Tree:
The expression directory tree is unchangeable, which means you cannot directly modify the expression directory tree. To change the expression directory tree, you must create a copy of the existing expression directory tree and perform the required changes when creating the copy. You can use the expression directory tree accessor to traverse the existing expression directory tree and copy each node it accesses. We can create a custom class to inherit the expressionvisitor, and specify the corresponding method in the Custom class to modify the Expression Tree.