I. Preface
I have always wanted to write an article about Dpper’s customized extension, but it will be designed to parse Lambda expressions, and to parse Lambda expressions, you must Know the relevant knowledge points of expression trees. I hope that by explaining more about the knowledge points or applications of each module, I can help gardeners to learn more. Although the explanation is not comprehensive, if it can be a key to open this piece, it would be more gratifying for the snail.
Second, expression tree understanding
The expression tree represents the code in a tree-shaped data structure, where each node is an expression, which we can directly write by the code. The logic of is stored in a tree-like structure in the form of expressions, so that the tree can be parsed at runtime, and then executed, to achieve dynamic editing and execution of the code. Linq to SQL in .Net is the analysis of expression trees.
Here we will first explain the expression and expression tree. I believe everyone knows that expressions, such as x+5 or 5, can be regarded as expressions, and the tree in the expression tree refers to the binary tree. It is a collection of expressions. The Expression class in C# is an expression class. For an expression tree, the leaf nodes are all parameters or constants, and the non-leaf nodes are all operators or control symbols.
2.1. Creation of expression
Lambda expression method:
Expressionint, int,bool>> fun = (x, y) => x
The expression root node type created by this method is ExpressionType.Lambda, and the Type type is the return value type typeof(bool) p>
Assembly method (create expression tree through API):
ParameterExpression numParam = Expression.Parameter( typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int)) ;
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expressionint, bool>> lambda1 =
Expression.Lambdaint, bool>>(
numLessThanFive,
new ParameterExpression[] {numParam });
We first created two parameter expressions num And 5, and then assembled together with LessThan, the final expression is "num<5", the node type of expr is LessThan, and the Type type is typeof(bool)
Let’s take a look at the expression tree first The structure of
First of all, the function of Expression
Expression
The Body in LambdaExpression is our expression.
C# expression provides us with a wealth of expression classes, enter the LambdaExpression class
Methods whose return type ends with "Expression" are basically an expression class.
For the definition and creation method of each expression, please refer to the official Microsoft document https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.binaryexpression?view =netframework-4.8
The following are the most commonly used expressions
ConstantExpression: Constant expression
>
ParameterExpression: Parameter Expression
UnaryExpression: Unary operator expression
BinaryExpression: Binary operator expression
TypeBinaryExpression: is operator expression
ConditionalExpression: conditional expression
MemberExpression: access field or attribute expression
MethodCallExpression: Call member function expression
Expression
2.2. Expression analysis< /h3>
Expression tree analysis
We can know from the LambdaExpression class that the expression tree contains: parameters [Parameters], expression tree type [NodeType], expression [Body], return type [ReturnType], the delegate of the Lambda expression [Compile] and the name of the Lambda expression [name], as shown in the figure:
Expression analysis:
All expressions include: left node [Left], right node [Right], type [NodeType] , Different expressions will have other attributes, and the left and right nodes here are still expressions.
The image below is a screenshot of BinaryExpression expression
Expression tree and the type NodeType in the expression It is an enumeration, with a total of 85 types, friends who are interested can go and learn about it.
The commonly used types are as follows:
ExpressionType.And: similar to &
ExpressionType.AndAlso: C# is similar to &&
ExpressionType.Or span>: Similar in C#|
ExpressionType.OrElse: Similar in C#||
ExpressionType.Equal: Similar to ==
ExpressionType.NotEqual in C# : Similar in C#!=
ExpressionType.GreaterThan: Similar in C#>
ExpressionType.GreaterThanOrEqual: Similar to >=
ExpressionType.LessThan: C# in C# Similar to <
ExpressionType.LessThanOrEqual: similar to <=
ExpressionType.Add: similar to +
in C#
ExpressionType.AddChecked: similar to in C# +
ExpressionType.Subtract: C# is similar to -
ExpressionType.SubtractChecked: C# is similar to -
ExpressionType.Divide: C# is similar to/
ExpressionType.Multiply: C# Similar to *
ExpressionType.MultiplyChecked: similar to *
in C#
2.3, Compile expression tree< /h3>
At the expression creation, we created a Lambda expression in combination, so how should we use it? In "Expression Analysis", both LambdaExpression class and Expression
The code is modified as follows:
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int)) ;
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expressionint, bool>> lambda1 =
Expression.Lambdaint, bool>>(
numLessThanFive,
new ParameterExpression[] {numParam }); Console.WriteLine($"Lambda content: {lambda1.ToString()}"); //Expression compilation var func = lambda1.Compile(); Console.WriteLine($"Lambda operation result: {func(6)}");
Run results
Three. Summary
here We have done a basic explanation of expressions. I believe everyone has a preliminary understanding of Lambda expressions. Below we will continue to explain the traversal of an expression tree.
Expressionint, int< /span>,bool>> fun = (x, y) => x , bool>> lambda1 = ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int)) ;
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expressionint
Expression.Lambdaint, bool>>(
numLessThanFive,
new ParameterExpression[] {numParam });
ParameterExpression numParam = Expression.Parameter( typeof(int), " num");
ConstantExpression five = Expression.Constant(5, typeof(int)) ;
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expressionint, bool>> lambda1 =
Expression.Lambdaint, bool>>(
numLessThanFive,
new ParameterExpression[] {numParam }); Console.WriteLine($"Lambda content: {lambda1.ToString()}"); //Expression compilation var func = lambda1.Compile(); Console.WriteLine($"Lambda operation result: {func(6)}");