Preface
In the previous article, we learned what are expression trees, what are delegates, and their relationships. May be my skill is not good, seemingly everyone is not concerned about, did not explain the problem of different angles.
Learning a new technology is a dull process that can only be fun when you have mastered it and can use it.
The development of the program is a very strange group of people, we can actually through the dense English characters and punctuation to find fun, it is really strange.
Considering that you need a process to reach new technologies:
In fact, for many people is not a new technology, but you will be patient to read the following article, that you may use this technology is not very skilled
So I'm not going to come up with a bunch of code and then explain what it is and what it is because it's going to touch a lot of new keywords, and it's going to be painful to learn.
All the later sections of this series only introduce a new concept in each article, so that you can learn to reduce the scope of learning.
And then let's get a thorough understanding of each type of action, and I'll work on the new type of each topic in three ways, using lambda, dynamic construction, and the structure of the expression tree .
What is LambdaExpression
LambdaExpression is inherited from Expression . LambdaExpression's specific performance is:expression<func<>> or expression<action<>>
It doesn't matter, see the example below to find out
First, let's take a look at its explanatory notes on MSDN:
Describes a lambda expression. This captures code blocks that are similar to the. NET method body.
Look at the MSDN note, we still do not understand what it means, in layman's words: a piece of code that contains an expression of arithmetic , is lambdaexpression.
Well, I said, my foundation is not good, the more you see the more you do not understand ....... (even worse than MSDN explained)
Definition of LambdaExpression
Expression<Func<int,int1; Expression<Action<int12;
This through o=> ... The definition is lambdaexpression. Back to what I said above:
A section of code that contains an expression of an operation is lambdaexpression.
Does this look easier to understand? Of course, the above only does the addition operation, of course, not only these operations, such as:
Expression<Funcobject1"steden"" Farseer.net")
Another example is in our LINQ to Object (This is, of course, a purely delegate type: Func<int,bool>, but it is also a lambda expression (note that it is not an expression tree))
var New list<int>(); lst. Where0);
These are the definitions of lambda. And we also learned in the previous article how to convert expression<func<uservo,object>> into func<uservo,object>.
What's the use of lambdaexpression?
At this time the smart reader will think, that is, I can directly define the O=>, ..., why do you want to understand lambdaexpression, anyway, the C # compiler will turn it into lambdaexpression, do not care about us at all.
That's true, if we don't need to construct it dynamically
I mean to build it dynamically while the program is running, not to define it when writing code
, you do not have to worry about whether it is lambdaexpression, just define the code on the line.
However, in many scenarios, we need to construct it dynamically, and then pass it on to other places, so that they can parse it, for example:
Scenario: In a system hierarchy, we have an entity class, such as the name: Uservo (which belongs to the Xxx.entity class library). In our bottom-up, we need to dynamically generate some "common" operations (such as the Tombstone function) on the entity classes. But we know that the bottom layer does not know what data types are in the upper layer, or even who is called and does not know. So at this point, I have to create it in a dynamically constructed way. (because I have no idea uservo this class)
In fact, the examples above are not just lambdaexpression, but other expression as well.
Before talking about dynamic construction, I think we should let everyone learn how to parse it, our study is to understand its internal structure, and then better know how to construct it, is not it?
Analysis of LambdaExpression
This is going to take out our great ExpressionVisitor class. In fact, the class was repackaged in my farseer.net ORM Framework (not yet published, published after V1.2 , and I'll post an address later)
There is an entry method:
protected Virtual Expression Visit (Expression exp)
ExpressionVisitor accesses this expression tree in visitor mode (design mode). You can see that there is a:exp. The NodeType property, which is returned by:Expressiontype enumeration:
protected Virtualexpression Visit (expression exp) {if(exp = =NULL) returnexp; Switch(exp.NodeType) { Caseexpressiontype.negate: Caseexpressiontype.negatechecked: CaseExpressiontype.not: CaseExpressiontype.convert: Caseexpressiontype.convertchecked: Caseexpressiontype.arraylength: CaseExpressiontype.quote: CaseExpressiontype.typeas:return This. Visitunary ((unaryexpression) exp); CaseExpressiontype.add: Caseexpressiontype.addchecked: Caseexpressiontype.subtract: Caseexpressiontype.subtractchecked: Caseexpressiontype.multiply: Caseexpressiontype.multiplychecked: CaseExpressiontype.divide: CaseExpressiontype.modulo: CaseExpressiontype.and: Caseexpressiontype.andalso: Caseexpressiontype.or: CaseExpressiontype.orelse: CaseExpressiontype.lessthan: Caseexpressiontype.lessthanorequal: CaseExpressiontype.greaterthan: Caseexpressiontype.greaterthanorequal: Caseexpressiontype.equal: Caseexpressiontype.notequal: CaseExpressiontype.coalesce: CaseExpressiontype.arrayindex: CaseExpressiontype.rightshift: CaseExpressiontype.leftshift: CaseExpressiontype.exclusiveor:return This. VisitBinary ((binaryexpression) exp); CaseExpressiontype.typeis:return This. Visittypeis ((typebinaryexpression) exp); Caseexpressiontype.conditional:return This. Visitconditional ((conditionalexpression) exp); Caseexpressiontype.constant:return This. Visitconstant ((constantexpression) exp); CaseExpressiontype.parameter:return This. Visitparameter ((parameterexpression) exp); Caseexpressiontype.memberaccess:return This. Visitmemberaccess ((memberexpression) exp); CaseExpressiontype.call:return This. VisitMethodCall ((methodcallexpression) exp); Case ExpressionType.Lambda:return. Visitlambda ((lambdaexpression) exp); Caseexpressiontype.new:return This. Visitnew ((newexpression) exp); CaseExpressiontype.newarrayinit: CaseExpressiontype.newarraybounds:return This. Visitnewarray ((newarrayexpression) exp); CaseExpressiontype.invoke:return This. Visitinvocation ((invocationexpression) exp); CaseExpressiontype.memberinit:return This. Visitmemberinit ((memberinitexpression) exp); CaseExpressiontype.listinit:return This. Visitlistinit ((listinitexpression) exp); default: Throw NewException (string. Format ("unhandled expression type: ' {0} '", exp. NodeType)); }
Then one by one parsing is performed based on the incoming expression tree, and you can see that when the case goes to Expressiontype.lambda , it is cast to lambdaexpression
and passed into the Visitlambda method:
protected Virtual Expression Visitlambda (lambdaexpression Lambda) { this. Visit (lambda. Body); if (Body ! = lambda. Body) { return expression.lambda (Lambda. Type, body, lambda. Parameters); } return Lambda; }
In fact, this code does not have to be too much to understand other parts, just need to know:
When expression NodeType = = Expressiontype.lambda , it is possible to display the conversion to: LambdaExpression.
And it has a property called Body: (Gets the body of the lambda expression.) ), and a property called parameters: ( Gets the parameters of the lambda expression.) )
Body Returns the body of the lambdaexpression.
Principal: Refers to the main structure in the LambdaExpression, or the main expression. such as the red mark part:
o = o.id! = 1 && (O.username = = "Steden" | | o.username = = "Farseer.net")
The Parameters return is the parameter expression tree (a term is presented, which is explained in detail in the next article). Here's a simple explanation: The o that appears above is the parameter, and the type of O is Uservo
Then the above:Visitlambda Method continues to access: this. Visit (lambda. Body), which is the interpretation of the body part .
From the expression code above (the red part), it executes: this. VisitBinary ((binaryexpression) exp); method.
Here you know Binaryexpression (represents an expression that contains a two-tuple operator. It is enough to parse the && above.
In the previous article we emphasized that expression is a data structure , that is, the red part, the code we define is essentially stored in a data structure ,
The red Bottom is: The Binaryexpression type, which represents an expression that contains a two-tuple operator. ) Two-dollar operation, such as && | | >= <! =
The Blue bottom is: The ParameterExpression type, which represents the named parameter expression. ) parameters passed in, such as Uservo entity classes
The Green Bottom is: The ConstantExpression type, which represents an expression with a constant value. ) a specific constant value.
The structure of LambdaExpression
The time is too late to stay in the day to improve.
Summarize
The time is too late to stay in the day to improve.
What is lambdaexpression, how to convert to Func or action (2)