[READER] [learn LinqExpression and Reflection (Emit)] Read ExampleFromTheArticle and linqexpression of TypeBuilderSample

Source: Internet
Author: User

[READER] [learn LinqExpression and Reflection (Emit)] Read ExampleFromTheArticle and linqexpression of TypeBuilderSample

Preface

About "Reader"

The saying goes: "reading a thousand books and traveling a thousand miles". By reading more excellent code, we can not only improve our ability to read code (easy to maintain or communicate with each other), but also learn a lot of knowledge that we need to grow. Only by reading more can we broaden our horizons and remind us that the road ahead is still long.

Looking back at your own growth path, I have been reading it on CodeProject since I got started with C. I have a deep understanding of the importance of reading to our ability improvement. (This account has been registered for a long time and has not contributed much. Sorry)

Reading is an exploratory learning. You can select a knowledge point in the demo. If you are reading a project, you can also perform breakpoint debugging and change the prerequisites, verify your conjecture about and deepen your understanding of the API. These are much better than Directly Reading API documents and reading books. In addition, if you feel helpful and enlightening code, you can save it as your accumulation for future reference and calling.

If I have time, I will occasionally share some reading notes under this category. If you are interested, read them together.

 

Demo address: Fluent Method and Type Builder (download by yourself)

Objective: To learn more about Linq. Expression, System. Reflection, and System. Reflection. Emit. At the same time, this tool is also very useful in the dynamic creation of methods and types (such as AOP.

 

Point 1: Why is the method being used:

string fileName = null;var method =   new FluentMethodBuilder(typeof(void)).  AddParameter(() => fileName).

The Expression "() => fileName". When accessing AddParameter, the Expression type is MemberExpression and Expression. Member. MemberType = MemberType. Field? 'Filename' is a local variable?

Answer: see StackOverFlow.

class C{  void M()  {    int x = 1;    Func<int, int> f = y=>x+y;  }  }

Actually compiled:

 
class C{  private class DisplayClass  {    public int x;    public int AnonymousMethod(int y)    {       return this.x + y;    }  }  void M()  {    C.DisplayClass d = new C.DisplayClass();    d.x = 1;    Func<int, int> f = d.AnonymousMethod;  }}
 

 

 

Point 2: basic attributes of MemberExpression:MSDN

Member: Get the attribute or field pointed to by the expression [first interaction with System. Reflection, return type is System. Reflection. MemberInfo]

Expression: gets the object that contains the attribute or field pointed to by the Expression.

Type: the Type of the delegate in the expression.

NodeType: a subdivision of the expression type, which must be subdivided into addition, subtraction, and so on in binary operation expressions.

Breakpoint debugging found:

Expression: () => xxx. fileName NodeType is Lambda

Expression. Body xxx. fileName NodeType is MemberAccess

Body. Expression xxx NodeType is Constant

(ConstantExpression) Body. Expression). Value can access the xxx object. Through the watch window, you can view the attributes of this anonymous class and prove the conclusion in 1)

 

 

Point 3: ParameterExpression

IsByRef: whether it is a reference type

Name: Parameter Name

 

Generation: Expression. Parameter (fieldType, fieldName) or Expression. Variable (fieldType, fieldName)

Additional learning points:

A. Generate the ref parameter type: fieldType = fieldType. MakeByRefType ();

B. Packing type: fieldType = typeof (Box <>). MakeGenericType (fieldType); (Lenovo typeof (Nullable <>). MakeGenericType ). (What if I want to obtain the Box type from the generic type "Box <x>? In actual code)

 

 

Point 4: Using implementation

var result =                Expression.Block                (                    new ParameterExpression[]{otherVariable},                    Expression.Assign(otherVariable, _usingValue),                    Expression.Assign(_usingVariable, otherVariable),                    Expression.TryFinally                    (                        base._CompileToExpression(),                        Expression.IfThen                        (                            Expression.NotEqual(otherVariable, Expression.Constant(null)),                            Expression.Block                            (                                Expression.Assign(_usingVariable, Expression.Constant(null, _usingVariable.Type)),                                Expression.Call(otherVariable, _disposeMethod)                            )                        )                    )                );

We can see the implementation of the Using statement. In LinqExpression, TryFinally (expBody, expFinally) is essentially used ).

 

Additional knowledge points:

A. Expression can assemble and execute statements together;

B. Value assignment and If statement implementation: Expression. Assign and Expression. IfThen. In Demo, the type of _ usingValue is MemberAccess, that is, xxx. StreamReader;

C. The second interaction with System. Reflection: Expression. Call (varableExp, methodInfo ).

 

 

Point 5: Implementation of loop statements

var innerBody = base._CompileToExpression();            var result =                Expression.Block                (                    Expression.Label(ContinueTarget),                    innerBody,                    Expression.Goto(ContinueTarget),                    Expression.Label(BreakTarget)                );            return result;

It can be found that the loop statement is implemented through GoTo this year. Two labels are created at the entry and exit of the loop body, and the program jumps to the entry of the loop body after execution; if you want to interrupt the program during execution, just jump to the exit of the loop statement.

 

Then, in innerBody, there must be a statement to jump to the Break, which can be seen from the Break () method:

_IBlockBuilder instance = this;while(instance != null){    _ILoop loop = instance as _ILoop;    if (loop != null)    {        var gotoExpression = Expression.Goto(loop.BreakTarget);        var statement = new _Expression(gotoExpression);        _statements.Add(statement);        return _this;    }    instance = instance.Parent as _IBlockBuilder;}

The process also requires attention: traverse from the current Block-level statements step by step, and use Goto BreakTarget to interrupt the first-level Loop closest to the current Block.

 

Point 6: Expression Visitor

In row 372 of FluentMethodBuilder, there is the following sentence:

body = _visitor.Visit(body);

Let's take a rough look at the Code, especially the VisitMember method. It seems that the corresponding expression is found in the context based on the node. Can't you do it? Certainly not. Otherwise, the author will not write it.

So what exactly does it do?

First, let's take a look at it: F5, and an error will be reported, which means that the streamreader parameter path cannot be null. It seems that the assigned value is not passed, but what is the specific reason?

Cancel the previous comments, set a breakpoint before and after the "visit" Statement, check the DebugView of the body, and compare it with the following code ):

 

// $ Var1 =. new System. IO. streamReader (. constant <TypeBuildingSample. program + <> c _ DisplayClass0> (TypeBuildingSample. program + <> c _ DisplayClass0 ). fileName) // $ var1 =. new System. IO. streamReader ($ fileName );

This is why visit is not used. When the method is executed, the culprit of the null parameter error is reported. Because we used the fileName field of the anonymous class, instead of the parameter we passed in!

Think about the previous Code: Using () => streamReader, () => new StreamReader (fileName), and pass the local variable to StreamReader as a parameter, if you do not use visit, such a statement will certainly appear.

So do not use local variables? No, because we cannot access its own local variables outside of a method, so the author first replaces it with the local variables of the upper-level method, then, use Visitor to restore it to "real local variables" without relying on the local variables in the upper-level method.

Therefore, ExpressionVisitor does what it does. It can be seen from this that it can traverse and modify sub-elements (subnodes of the syntax tree) in the Linq Expression ).

 

Point 7: implementation and overall implementation of concatenation

The first is the design mode, which is used as a whole.Combination ModeTo generate a tree system. The subnode implements the ICompile interface. Every time a new node is generated, it is added to the statements of the parent node, and finally traversed to the root node to generate the total statements. If we divide it forward, we will also find that a class can be divided into attributes, methods, fields, Event code, etc. The method code can also be divided into loop blocks and condition blocks, using blocks. These blocks can be nested with each other...

The concatenation method is implemented by using the EndXXX () method. This method returns the parent node of the child node, so that you can continue to call the members of the parent node without interrupting the statement.

 




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.