ArticleDirectory
- Starting with expressions
- Expression Tree
- Lambda expressions
- Meaning of Expression Tree: data-based Expression
- Exercise
As you may know, Expression Tree is a new feature introduced by. Net 3.5. Many friends have heard of this feature, but they have not yet had time to understand it. Look at Lao Zhao and many other cool people in the blog Park and make Expression Tree dazzled. Do you often feel a little outdated? In fact, Expression Tree is a one-to-one feature. As long as you have a certain understanding of its basic concepts, you can use it in countless ways. If you have some knowledge about reflection, generics, and so on, you will find that adding Expression Tree is definitely a good helper in your work. If you are a newbie to expression tree, you will be able to get familiar with this tool from the beginning of this article, and then read Lao Zhao's article again ~
Starting with expressions
Expression Tree indicates the Expression Tree. Many people will think of lambda expressions, delegation, and LINQ. But the most basic concept is "expression ". Now let's forget all the terms to understand the expressions again.
Expression is today'sProgramming LanguageThe most important component. Simply put, an expression is a combination of variables, values, operators, and functions, indicating a specific expression. For example, the following are all (C #) Expressions:
3// Constant expressionA// Variable or parameter expression! A// One-dimensional Logical non-expressionA + B// Binary addition expressionMath. Sin ()// Method call expressionNewStringbuilder()// New Expression |
In addition, there are many address expressions, new array expressions, and value assignment expressions. As you can see, expressions can often represent a value or object. Therefore, in strong-type languages such as C #, expressions often have a corresponding type. For example, the expression "3" is of the int type. However, sometimes the expression does not have a value, such as a method call expression. If the method does not return a value, the expression does not have a value. In this case, the expression type is void.
An important feature of an expression is that it can be infinitely combined as long as it conforms to the correct type and semantics. For example, if + can be used for addition of various numeric types, the plus sign can be an expression of any type corresponding to the value. It can be a function call and a constant: Math. Sin (A) + 3; it can also be an addition expression A + 2 + 3. We must have used this feature for a long time in practice. So how does a + 2 + 3 Calculate the correct value? Calculate the result B of (a + 2) and then the value of B + 3. If we use a graph to represent this process, it is like this:
Similarly, the expression math. Sin (A) + 3 can also be expressed as follows:
As you can see, all expressions can be represented in the same tree structure. Each node and all its descendants form an independent expression. If we express the expression in this structure, we can easily understand its operation rules and steps. Therefore, we can use a tree-like Data Structure to represent each expression. The data structure is the expression tree.
Expression Tree
As mentioned earlier, the expression tree is a data structure that represents the expression. The expression class in the namespace of system. LINQ. Expression and Its subclasses are the implementation of this data structure. Each expression can be represented as an instance of a subclass of expression. Each expression subclass stores its own subnodes according to the characteristics of the corresponding expression. For example, binaryexpression represents the expressions of various binary operators. Its left and right attributes are the two values involved in the binary operation. The following describes the specific internal structure of each expression as the "component" of the expression ". For example, a Binary Expression consists of a left arithmetic expression, a right arithmetic expression, and an operator.
The constructors of each subclass of expression are not public. To create an Expression Tree, you can only use the static methods provided by the expression class. (This also indicates that the expression tree system cannot be expanded by itself.) If we want to create an Expression Tree of 1 + 2 + 3, we can write it like this:
ConstantexpressionExp1 =Expression. Constant (1 );ConstantexpressionExp2 =Expression. Constant (2 );BinaryexpressionExp12 =Expression. Add (exp1, exp2 );ConstantexpressionExp3 =Expression. Constant (3 );BinaryexpressionExp123 =Expression. Add (exp12, exp3 ); |
This should be very understandable. What if we want to write the Expression Tree of the expression math. Sin (? The problem arises. "A" here does not know what to use. To solve this problem, the following Lambda expression is coming soon.
Lambda expressions
Lambda is also a new expression introduced by C #3.0/vb9. We all know that it is related to previous anonymous functions and delegation. However, I still forget this for the moment, and fully consider the lambda expression as a new expression. We have seen various expressions, some representing a constant, some representing a variable, some representing addition, and some representing function calls. Lambda expressions, as an expression, expressFunction. Lambda expressions are composed of a series of parameters plus an expression that represents the function logic.
(Parameters) => Expression |
The most important feature of a Lambda expression is that it can introduce a batch of parameters that can be used in the function body expression. Based on this feature, we can create an Expression Tree with custom variables, and these custom variables are represented as parameters of lambda expressions:
parameterexpression expa = Expression . parameter ( typeof ( double ), "A" ); // parameter A methodcallexpression expcall = Expression . call ( null , typeof ( math ). getmethod ( "sin" , bindingflags . static | bindingflags . public), expa); // math. sin (a) lambdaexpression exp = Expression . lambda (expcall, expa); // A => math. sin (a) |
Here we use a new expression Tree node-methodcallexpression. It indicates a method call. The method is represented by a methodinfo instance. If you draw a graph, the lambda expression can be drawn as follows:
It can be seen that using lambda expressions to represent a function is a very intuitive process. Sometimes we really think that a function without a name is a real function. Because a function only requires two components: parameter and function body, the name is only required to reference it elsewhere.
So far, we have understood the basic concepts of the Expression Tree. However, we can only build an Expression Tree step by step using the most primitive method. The lambdaexpression we used earlier is applicable to various types of functions.. Net also provides a lambdaexpression <tdelegate> type suitable for specific Delegate types. We use it to represent a strongly typed lambdaexpression. Now we need to introduce the bridge between the true expressions of C # and VB and the Expression Tree -- Expression Tree literals ),The Lambda expression tree can be automatically generated from the lambda expression.:
Expression<Func<Double,Double> Exp = A =>Math. Sin (); |
Note that the value assignment statement has a strong lambdaexpression: expression <func <double, double> on the left. A real C # syntax Lambda expression is displayed on the right. In this case, the C # compiler can automatically generate the Expression Tree of the lambda expression on the right. That is to say, this exp is basically the same as the lambda Expression Tree we just generated manually. Note that this special syntax can only obtain the Expression Tree from lambda expressions. Other expressions cannot automatically generate the Expression Tree. However, once lambda expressions are obtained, internal expressions can be obtained directly from its subnodes. This is a very useful syntax and requires a deep understanding of its role.
Note that the delegate type func <double, double> has a dual effect. First, it limits the generated Expression Tree to a one-dimensional Lambda function that accepts double and returns double; second, this delegate can be directly used in the compilation of the lambda Expression Tree, and can be processed as a strong type in C. We will discuss this issue in detail later when compiling the Expression Tree.
Meaning of Expression Tree: data-based Expression
We can now create an Expression Tree in two ways-use expression nodes or directly generate a Lambda expression from C # and VB. No matter which method is used, we finally get the data in a tree structure in the memory. If you want to, you can restore it to text.Source codeOr serialized into a string. NOTE: If it is a C # expression, we cannot output or serialize it. It only exists in the source file before compilation. The Expression Tree is now a type of data, not a language expression. We can process this data at runtime, precisely understand its internal logic, and pass it to otherProgramOr compile it again to be executable.Code. This can be summarized into three basic uses of the Expression Tree:
- Runtime analysis expression Logic
- Serialization or transmission expression
- Re-compile into executable code
In the next article, we will focus on the usage of the three in actual development.
Exercise
Are there any exercises? Don't worry, you can use the following questions as materials for practice on the computer, so that you can quickly understand what you learned this time.
Question 1: Draw the Expression Tree of the following expressions. At the beginning, you may not know that some operations are actually expressions (such as the array operator A [2]), but it does not matter. The following exercises will help you verify this.
-
A + B * 2
Math. Sin (x) + math. Cos (y)
New stringbuilder ("hello ")
New int [] {A, B, A + B}
A [I-1] * I
A. length> B | B> = 0
(Difficult) New system. Windows. Point () {x = math. Sin (A), Y = math. Cos ()}
Tip: Pay attention to the operator priority. The second-to-last question of A is of the string type. You can use any suitable simple type for other variables. If you want to know what the above expressions are, you can check msdn.
Question 2: extract the variables in the above expressions into parameters and express them as lambda expressions. Then the expression static method is gradually combined to build them.
For example, if a + B * 2 is written as a Lambda expression (int A, int B) => A + B * 2. According to the previous math. Sin (a) example, use the expression method to combine this logic.
Question 3: Verify the result of your second question. The expression instance tostring () is generated, and its expression prototype is displayed. Check whether the constructed expression tostring () is correct.
If you find that the generated expression is not what you want to build and you do not know how to do it, you can use the expression tree literal syntax to let the C # compiler generate it for you. Then decompile it with reflector to see the correct expression tree. However, the C # compiler sometimes uses some cheating techniques. You should be smart enough to find a way to bypass ......
Address: http://www.cnblogs.com/Ninputer/archive/2009/08/28/expression_tree1.html