[. Net Object-Oriented programming advanced] (7) Lamda expressions (3) Expression Tree advanced applications, lamda expressions

Source: Internet
Author: User

[. Net Object-Oriented programming advanced] (7) Lamda expressions (3) Expression Tree advanced applications, lamda expressions

[. Net Object-Oriented programming advanced] (7) Lamda expressions (3) Expression Tree advanced applications

This section introduces:After discussing the definition and resolution of the Expression Tree, we know that the expression tree is not executable code, but the data structure after the expression is objectized. It is time to reference it to solve the problem. This section mainly aims to use the expression tree to solve practical problems.

Before reading: 

Before learning this section, you must have the following knowledge:

A. inherit from the three main features of [. net idea Object-Oriented Programming] idea (12) idea object-oriented-Inheritance 

B. polymorphism [. net runtime Object-Oriented Programming Basics] three major features of object-oriented architecture: Polymorphism 

C. abstract class [. net platform Object-Oriented Programming Basics] Objective Programming (15) abstract class 

D. Generic[. Net Object-Oriented Programming Basics] (18) Generic

1. dynamically create an Expression Tree 

After learning the Expression Tree Structure and resolution expression in the previous section, it is very easy to dynamically create the Expression Tree. Next we will use the expression tree to dynamically create the Lambda expression in the next section.

First, let's look at the original expression to be finalized:

Expression<Func<int, int, bool>> expression = (x, y) => x!=0 && x==y+1;

The dynamic creation process is as follows:

// Dynamically create Expression Tree expression <Func <int, int, bool> Expression = (x, y) => x! = 0 & x = y + 1; // create two parameters ParameterExpression [] parameters = new ParameterExpression [] {Expression. parameter (typeof (int), "x"), Expression. parameter (typeof (int), "y")}; ParameterExpression param1 = parameters [0]; ParameterExpression param2 = parameters [1]; // create the first expression x on the right first! = 0 // (1) Constant 0x ConstantExpression rightLeftRight = Expression. Constant (0, typeof (int); // (2) create the first Expression on the left x! = 0 BinaryExpression rightLeft = Expression. notEqual (param1, rightLeftRight); // create the second Expression x = y + 1 // (3) first create the right Expression y + 1 BinaryExpression rightRightRight = Expression. add (param2, Expression. constant (1, typeof (int); // (4) create the right Expression x = y + 1 BinaryExpression rightRight = Expression. equal (param1, rightRightRight); // 5) Create an expression on the right side of x! = 0 & x = y + 1 BinaryExpression Right = Expression. andAlso (rightLeft, rightRight); // (6) the Expression <Func <int, int, bool> lambdaExr = Expression. lambda <Func <int, int, bool> (Right, parameters); Console. write (lambdaExr. toString ());

The running result is as follows:

The above creation process is as follows:

2. Execution Expression Tree

After dynamically creating the above expression, we are sure that the final result is to use this expression to solve some problems. How can we execute the dynamically created Expression Tree?

This problem is very easy and requires only two steps:

A. Compiling programming Expression Tree as delegate

B. Call the Expression Tree (call the delegate)

The following is an example:

// Execute Expression Tree expression <Func <int, int, bool> Expression = (x, y) => x! = 0 & x = y + 1; Func <int, int, bool> result = expression. compile (); bool result2 = expression. compile () (9, 8); Console. writeLine (result2); Console. writeLine (result (3, 2); Console. writeLine (result (5, 4); Console. writeLine (result (6, 4); Console. writeLine (result (-6,-7 ));

The running result is as follows:

3. debug Expression Tree

When debugging an application, you can analyze the structure and content of the Expression Tree. To quickly understand the expression tree structure, you can use the DebugView attribute, which is only available in debug mode. Use Visual Studio for debugging. To better represent the content of expression A. Tree, the DebugView attribute uses the Visual Studio visualization tool.

In the data prompt, monitoring, automatic, or local variables window, click the magnifier icon next to the DebugView attribute of the Expression Tree. A list of visualization tools is displayed.

B. Click the visualization tool to use.

 

For example, we use text visualization tools.

$ Symbol, indicating Parameters

4. Modify the Expression Tree

The Expression Tree is unchangeable, which means you cannot directly modify the Expression Tree.

To change the expression tree, you must create a copy of the existing Expression Tree and perform the required changes when creating the copy. You can use the ExpressionVisitor class to traverse the existing Expression Tree and copy each node it accesses.

. NET has an ExpressionVisitor class that provides rewriting to modify the Expression Tree.

The following describes how to rewrite the VisitBinary method to change the node type on the left of the Expression Tree from & to |. The implementation is as follows:

public class OrElseModifier : ExpressionVisitor{    public Expression Modify(Expression expression)    {        return Visit(expression);    }    protected override Expression VisitBinary(BinaryExpression b)    {        if (b.NodeType == ExpressionType.AndAlso)        {            Expression left = this.Visit(b.Left);            Expression right = this.Visit(b.Right);            return Expression.MakeBinary(ExpressionType.OrElse, left, right, b.IsLiftedToNull, b.Method);        }        return base.VisitBinary(b);    }}

The call is as follows:

// Modify Expression Tree expression <Func <int, int, bool> Expression = (x, y) => x! = 0 & x = y + 1; OrElseModifier amf = new OrElseModifier (); Expression newExp = amf. modify (expression); Console. writeLine ("original expression:" + expression. toString (); Console. writeLine ("modified expression:" + newExp. toString ());

The running result is as follows:

For the above implementation, there are several points to note, the above. the class ExpressionVisitor provided by NET has many override methods for us to indirectly modify the expression and return a copy of the expression, that is, a new expression.

In the call phase, why do we use Modify (expression); To call it? In this case,. net uses a design pattern, namely the visitor pattern, during design.

We can see that VisitBinary is a protected member. Of course, we cannot modify the modifier of the original method during rewriting.

This can be detailed in [. net idea Object-Oriented Programming Basics] idea (13) idea object-oriented three major features-polymorphism section.

If I have time to write design patterns, I will write many articles related to the blog Park.

5. Use the expression tree to generate dynamic queries

Let's make an interesting example to classify and query my articles in the blog.

Step 1: first obtain the article list and store data through an object list.

Create an object first:

/// <Summary // my blog post entity class /// </summary> public class MyArticle {/// <summary> /// Article No. // </summary> public int id {get; set ;}//< summary> /// article title /// </summary> public string title {get; set ;} /// <summary> /// Abstr /// </summary> public string summary {get; set ;} /// <summary> /// release time /// </summary> public DateTime published {get; set ;} /// <summary> /// last update time /// </summary> public DateTime updated {get; set ;} /// <summary> /// URL /// </summary> public string link {get; set ;} /// <summary> /// recommended quantity /// </summary> public int diggs {get; set ;} /// <summary> /// page views /// </summary> public int views {get; set ;} /// <summary> /// number of comments /// </summary> public int comments {get; set ;} /// <summary> /// author /// </summary> public string author {get; set ;}}

Next, get the article

// Dynamic query of my articles in the blog garden // Step 1: Obtain the List of my articles in the blog garden <MyArticle> myArticleList = new List <MyArticle> (); var document = XDocument. load (" http://wcf.open.cnblogs.com/blog/u/yubinfeng/posts/1/100 "); Var elements = document. root. elements (); // before doing this, we first get the list of articles in my blog var result = elements. where (m => m. name. localName = "entry "). select (myArticle => new MyArticle {id = Convert. toInt32 (myArticle. elements (). singleOrDefault (x => x. name. localName = "id "). value), title = myArticle. elements (). singleOrDefault (x => x. name. localName = "title "). value, published = Convert. toDateTime (myArticle. elements (). singleOrDefault (x => x. name. localName = "published "). value), updated = Convert. toDateTime (myArticle. elements (). singleOrDefault (x => x. name. localName = "updated "). value), diggs = Convert. toInt32 (myArticle. elements (). singleOrDefault (x => x. name. localName = "diggs "). value), views = Convert. toInt32 (myArticle. elements (). singleOrDefault (x => x. name. localName = "views "). value), comments = Convert. toInt32 (myArticle. elements (). singleOrDefault (x => x. name. localName = "comments "). value), summary = myArticle. elements (). singleOrDefault (x => x. name. localName = "summary "). value, link = myArticle. elements (). singleOrDefault (x => x. name. localName = "link "). attribute ("href "). value, author = myArticle. elements (). singleOrDefault (x => x. name. localName = "author "). elements (). singleOrDefault (x => x. name. localName = "name "). value}); myArticleList. addRange (result );

Method for creating a query expression tree

Public static IQueryable <T> MySearchList (IQueryable <T> myArticleTable, T myArticle) {// step 2, dynamically query my articles // List <MyArticle> SearchMyArticleList = new List <MyArticle> (); // 1. we first define several query parameters (article title, browser count, release time) ParameterExpression myart = Expression. parameter (typeof (T), "article"); // Title ParameterExpression searchTitle = Expression. parameter (typeof (string), "searchTitle"); // Title ParameterExpression searchViews = Expression. parameter (typeof (int), "searchViews"); // number of views ParameterExpression searchPublished = Expression. parameter (typeof (DateTime), "searchPublished"); // create a month // 2. use the Expression tree to dynamically generate a query (query an article of a date) Expression left = Expression. property (myart, typeof (T ). getProperty ("published"); // Expression of the access attribute Expression right = Expression. property (Expression. constant (myArticle), typeof (T ). getProperty ("published"); // Expression of the access attribute Expression e1 = Expression. greaterThanOrEqual (left, right); // greater than or equal to // 2. use the Expression tree to dynamically generate a query (query by clicks) Expression left2 = Expression. property (myart, typeof (T ). getProperty ("views"); // Expression of the access attribute Expression right2 = Expression. property (Expression. constant (myArticle), typeof (T ). getProperty ("views"); // Expression of the access attribute e2 = Expression. greaterThanOrEqual (left2, right2); // 3. construct a dynamic query (query by number of clicks and month) Expression predicateBody = Expression. andAlso (e1, e2); // 4. construct a filter MethodCallExpression whereCallExpression = Expression. call (typeof (Queryable), "Where", new Type [] {typeof (T)}, myArticleTable. expression, Expression. lambda <Func <T, bool> (predicateBody, new ParameterExpression [] {myart}); // construct the sorted MethodCallExpression orderByCallExpression = Expression. call (typeof (Queryable), "OrderByDescending", new Type [] {typeof (T), typeof (int)}, whereCallExpression, Expression. lambda <Func <T, int> (left2, new ParameterExpression [] {myart}); // creates a query expression tree IQueryable <T> results = myArticleTable. provider. createQuery <T> (orderByCallExpression); return results ;}

Call Method

IQueryable <MyArticle> results = ExpressionTree <MyArticle>. mySearchList (myArticleList. asQueryable <MyArticle> (), new MyArticle () {views = 500, published = Convert. toDateTime ("2015-06")}); foreach (MyArticle article in results) Console. writeLine (article. title + "\ n [Release Date:" + article. published + "] [browser count:" + article. views + "]");

The running result is as follows:

We query articles with more than June 1 clicks after the release date of 500.

6. Key points:

This section describes how to dynamically create the Expression Tree, execute the Expression Tree, and debug the Expression Tree. Finally, it ends with a dynamic query blog, so that the friends can be familiar with the convenience of the Expression Tree in dynamic query.

[Highlights]: during my blog writing at night, Wang has been capturing me for N times, keeping me awake all the time, and finally finished this article. Below is a pretty photo of Wang:

 

========================================================== ========================================================== ====================

 Returned directory

<If it is helpful to you, please click here for recommendations. If yesDo not understand or make a mistakePoints, Please exchange more>

<If you have any difficulty reading this series of articles, please read. net Object-Oriented Programming basics first>

<Reprinted statement: technology requires a spirit of sharing. You are welcome to repost the article in this blog, but please note the copyright and URL>

. NET exchange group: 467189533

========================================================== ========================================================== ====================

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.