Expression IN Linq (advanced tutorial), linqexpression

Source: Internet
Author: User

Expression IN Linq (advanced tutorial), linqexpression
Directory

Preface

Series of articles

Expression Tree Parsing

Expression Tree Features

Compile Expression Tree

Summary

Preface

Let's first briefly review the content introduced in the previous article. The previous article introduces the basic concepts of the Expression Tree (The Expression Tree is also called the "expression directory tree" and represents language-level code in the form of data, it is an abstract syntax tree or a data structure), and two ways to create the Expression Tree directory tree: create a directory tree using a lambda expression and create it using a static API method. Because lambda expressions with statement bodies cannot be converted to the Expression Tree, and sometimes we have such requirements, you can choose static API method creation in. in. NET Framework 4, the API Expression Tree also supports value assignment expressions and control flow expressions, such as loops, condition blocks, and try-catch blocks.

Series of articles

A preliminary understanding of Lambda expressions in Linq

Lambda of Linq (advanced tutorial)

Implicit type, automatic attribute, initializer, and Anonymous class of Linq

Extended method of Linq

First Appearance of Expression of Linq

Expression Tree Parsing

We can use APIs to create an Expression Tree. Is there a way to parse the given expression tree and obtain each part separately? The answer is yes. Let's look at an example below.

There is an expression tree like this.

1 // create Expression Tree 2 Expression <Func <int, bool> expTree = num => num> = 5;

This can be parsed to obtain the respective parts

1 // create Expression Tree 2 Expression <Func <int, bool> expTree = num => num> = 5; 3 // obtain the input parameter 4 ParameterExpression param = expTree. parameters [0]; 5 // obtain the lambda expression topic section 6 BinaryExpression body = (BinaryExpression) expTree. body; 7 // get the right half of num> = 5 8 ConstantExpression right = (ConstantExpression) body. right; 9 // obtain the left half of num> = 5 10 ParameterExpression left = (ParameterExpression) body. left; 11 // obtain the comparison operator 12 ExpressionType = body. nodeType; 13 Console. writeLine ("parsed: {0} {1} {2}", left, type, right );

Output result

Is it nice? I don't know. Do you have a little inspiration for converting lambda expressions into SQL statements IN THE ORM framework? It doesn't matter. Let's continue to look at an example. If the database has a data table such as Person. Our project has a persistence class such as Person. Then we create a query method that returns the SQL statements of all adults older than or equal to 18 years old.

1 namespace Wolfy. ORMDemo 2 {3 class Program 4 {5 static void Main (string [] args) 6 {7 string SQL = Query <Person> (person => person. age> = 18); 8 Console. writeLine (SQL); 9 Console. read (); 10} 11 /// <summary> 12 // obtain the queried SQL statement 13 /// </summary> 14 /// <param name = "epression"> filtering Condition </param> 15 // <returns> </returns> 16 static string Query <T> (Expression <Func <T, bool> epression) where T: class, new () 17 {18 // get the input parameter 19 ParameterExpression param = epression. parameters [0]; 20 // obtain the lambda expression body part 21 BinaryExpression body = (BinaryExpression) epression. body; 22 // parse person. age23 Expression left = body. left; 24 string name = (left as MemberExpression ). member. name; 25 // get the right section of the subject 26 ConstantExpression right = (ConstantExpression) body. right; 27 // obtain the operator 28 ExpressionType nodeType = body. nodeType; 29 StringBuilder sb = new StringBuilder (); 30 // obtain all attributes of the object using reflection, and concatenate 31 Type = typeof (T) in the SQL statement ); 32 PropertyInfo [] properties = type. getProperties (); 33 sb. append ("select"); 34 for (int I = 0; I <properties. length; I ++) 35 {36 PropertyInfo property = properties [I]; 37 if (I = properties. length-1) 38 {39 sb. append (property. name + ""); 40} 41 else42 {43 sb. append (property. name + ","); 44} 45} 46 sb. append ("from"); 47 sb. append (type. name); 48 sb. append ("where"); 49 sb. append (name); 50 if (nodeType = ExpressionType. greaterThanOrEqual) 51 {52 sb. append ("> ="); 53} 54 sb. append (right); 55 return sb. toString (); 56} 57} 58 class Person59 {60 public int Age {set; get;} 61 public string Name {set; get;} 62} 63}

Output result

Is it convenient? If a lambda expression is input, it can be parsed within the orm framework and then converted to an SQL statement. That is, writing lambda is equivalent to writing SQL statements, and you don't have to worry about not writing SQL statements.

Expression Tree Features

The expression tree should be permanent. This means that if you want to modify an Expression Tree, you must copy the Expression Tree and replace the nodes to create a new expression tree.

So how to modify it?

You can use the ExpressionVisitor class to traverse the existing Expression Tree and copy each node it accesses.

Example

Add an AndAlsoModifier class to the project.

Modify AndAlse in the expression tree to OrElse. The Code is as follows:

1 using System; 2 using System. collections. generic; 3 using System. linq; 4 using System. text; 5 using System. threading. tasks; 6 using System. linq. expressions; 7 namespace Wolfy. the ExpressionModifyDemo 8 {9/* class inherits the ExpressionVisitor class AND is used to modify expressions that represent conditional AND operations. 10 * It changes these operations from condition AND to condition OR. 11 * for this reason, this class will override the VisitBinary method of the base type, because the condition AND expression is represented as a binary expression. 12 * in the VisitBinary method, if the expression passed to this method represents the condition AND operation, the 13 * Code constructs a new expression that contains the condition OR operator (instead of the condition AND operator. 14 * If the expression passed to VisitBinary does not represent the condition AND operation, the method is implemented by the Base class. 15 * The base class method constructs nodes similar to the input Expression Tree, but these nodes replace their subdirectory tree with the expression tree generated by the accesser recursively. */16 public class AndAlsoModifier: ExpressionVisitor17 {18 public Expression Modify (Expression expression) 19 {20 return Visit (expression); 21} 22 protected override Expression VisitBinary (BinaryExpression node) 23 {24 if (node. nodeType = ExpressionType. andAlso) 25 {26 Expression left = this. visit (node. left); 27 Expression right = this. visit (node. right); 28 // modify AndAlse to OrElse29 return Expression. makeBinary (ExpressionType. orElse, left, right, node. isLiftedToNull, node. method); 30} 31 return base. visitBinary (node); 32} 33} 34}

Test code

1 namespace Wolfy. expressionModifyDemo 2 {3 class Program 4 {5 static void Main (string [] args) 6 {7 Expression <Func <string, bool> expr = name => name. length> 10 & name. startsWith ("G"); 8 // The first 9 consoles. writeLine (expr); 10 AndAlsoModifier treeModifier = new AndAlsoModifier (); 11 Expression modifiedExpr = treeModifier. modify (Expression) expr); 12 // The last 13 Console. writeLine (modifiedExpr); 14 Console. read (); 15} 16} 17}

Output result

Summary: to modify the expression tree, you must inherit the ExpressionVisitor class AND rewrite its VisitBinary (if it is a binary expression similar to AND) method. For another example, if you want to change the value greater than or equal to smaller than or equal to, you can modify the VisitBinary method.

1 protected override Expression VisitBinary (BinaryExpression node) 2 {3 if (node. nodeType = ExpressionType. greaterThan) 4 {5 Expression left = this. visit (node. left); 6 Expression right = this. visit (node. right); 7 // modify> to <= 8 return Expression. makeBinary (ExpressionType. lessThanOrEqual, left, right, node. isLiftedToNull, node. method); 9} 10 return base. visitBinary (node); 11}

Result

Compile Expression Tree

Expression <TDelegate> type provides the Compile method to Compile the Code represented by the Expression tree into executable delegates.

Take the top Expression Tree as an example.

1 // create Expression Tree 2 Expression <Func <int, bool> expTree = num => num> = 5;

There is such an expression tree. Now, I want to directly enter a value and then get the result. What should I do? Yes.

1 // create Expression Tree 2 Expression <Func <int, bool> expTree = num => num> = 5; 3 // The Compile method compiles the lambda expression described in the expression tree into executable code and generates a delegate that represents the lambda expression. 4 Func <int, bool> func = expTree. Compile (); 5 // result 6 bool result = func (10); // true7 Console. WriteLine (result );
Summary

1. Through expression parsing, you can get all parts of the Expression Tree. You will find that if the parameter of the method you write is Expression <Func <t, t> type, you can better use the features of lambda expressions and perform operations more conveniently. In this example, we also briefly analyzed how Lambda expressions are parsed into SQL statements IN THE ORM framework, and hope to stimulate your interest.

2. The expression tree has a permanent feature. Once created, if you want to modify an Expression Tree, you must copy the Expression Tree and replace the nodes to create a new expression tree. For more information, see the preceding example.

3. The Expression Tree compiled using the Complie method is a delegate. The method body of the delegate is the lambda expression in the expression tree. You can use it like a delegate. Sometimes you can use it in a similar way.

1 bool result = expTree.Compile()(10);

References

Http://msdn.microsoft.com/zh-cn/library/bb397951.aspx

Http://msdn.microsoft.com/zh-cn/library/bb546136.aspx

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.