国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Linq之Expression進階

2019-11-17 02:37:37
字體:
來源:轉載
供稿:網(wǎng)友

Linq之ExPRession進階

目錄

寫在前面

系列文章

表達式樹解析

表達式樹特性

編譯表達樹

總結

寫在前面

讓我們首先簡單回顧一下上篇文章介紹的內(nèi)容,上篇文章介紹了表達式樹的基本概念(表達式樹又稱為“表達式目錄樹”,以數(shù)據(jù)形式表示語言級代碼,它是一種抽象語法樹或者說是一種數(shù)據(jù)結構),以及兩種創(chuàng)建表達式樹目錄樹的方式:以lambda表達式的方式創(chuàng)建,通過API靜態(tài)方法創(chuàng)建。由于不能將有語句體的lambda表達式轉換為表達式樹,而有時我們又有這樣的需求,那么這種情況你可以選擇API的靜態(tài)方法方式創(chuàng)建,在 .NET Framework 4 中,API 表達式樹還支持賦值表達式和控制流表達式,比如循環(huán)、條件塊和 try-catch 塊等。

系列文章

Linq之Lambda表達式初步認識

Linq之Lambda進階

Linq之隱式類型、自動屬性、初始化器、匿名類

Linq之擴展方法

Linq之Expression初見

表達式樹解析

我們可以通過API方式創(chuàng)建表達式樹,那么我們有沒有辦法,將給定的表達式樹進行解析,分別得到各個部分呢?答案是肯定,下面看一個例子。

有一個這樣的表達式樹

1  //創(chuàng)建表達式樹2             Expression<Func<int, bool>> expTree = num => num >= 5;

可以這樣來解析,分別得到各個部分

 1             //創(chuàng)建表達式樹 2             Expression<Func<int, bool>> expTree = num => num >= 5; 3             //獲取輸入?yún)?shù) 4             ParameterExpression param = expTree.Parameters[0]; 5             //獲取lambda表達式主題部分 6             BinaryExpression body = (BinaryExpression)expTree.Body; 7             //獲取num>=5的右半部分 8             ConstantExpression right = (ConstantExpression)body.Right; 9             //獲取num>=5的左半部分10             ParameterExpression left = (ParameterExpression)body.Left;11             //獲取比較運算符12             ExpressionType type = body.NodeType;13             Console.WriteLine("解析后:{0}   {1}    {2}",left,type,right);

輸出結果

是不是很爽?不知道到這里,你是否對ORM框架中,lambda表達式是如何轉化為sql語句有那么一點點的靈感?沒有沒關系,咱們繼續(xù)看一個例子。如果數(shù)據(jù)庫中有Person這樣的一個數(shù)據(jù)表。咱們項目中有對應的Person這樣的一個持久化類。那么我們創(chuàng)建一個這樣的一個查詢方法,返回所有齡大于等于18歲的成年人的sql語句。

 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         /// 得到查詢的sql語句13         /// </summary>14         /// <param name="epression">篩選條件</param>15         /// <returns></returns>16         static string Query<T>(Expression<Func<T, bool>> epression) where T : class,new()17         {18             //獲取輸入?yún)?shù)19             ParameterExpression param = epression.Parameters[0];20             //獲取lambda表達式主體部分21             BinaryExpression body = (BinaryExpression)epression.Body;22             //解析 person.Age23             Expression left = body.Left;24             string name = (left as MemberExpression).Member.Name;25             //獲取主體的右部分26             ConstantExpression right = (ConstantExpression)body.Right;27             //獲取運算符28             ExpressionType nodeType = body.NodeType;29             StringBuilder sb = new StringBuilder();30             //使用反射獲取實體所有屬性,拼接在sql語句中31             Type type = typeof(T);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 }

輸出結果

是不是很方便?傳進來一個lambda表達式,就可以通過orm框架內(nèi)部解析,然后轉化為sql語句。也就是通過編寫lambda就等于寫了sql語句,也不用擔心不會寫sql語句了。

表達式樹特性

表達式樹應具有永久性。這意味著如果你想修改某個表達式樹,則必須復制該表達式樹然后替換其中的節(jié)點來創(chuàng)建一個新的表達式樹。

那如何修改呢?

可以通過ExpressionVisitor類遍歷現(xiàn)有表達式樹,并復制它訪問的每個節(jié)點。

一個例子

在項目中添加一個AndAlsoModifier 類。

將表達式樹中的AndAlse修改為OrElse,代碼如下:

 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.ExpressionModifyDemo 8 { 9     /*該類繼承 ExpressionVisitor 類,并且專用于修改表示條件 AND 運算的表達式。 10      * 它將這些運算從條件 AND 更改為條件 OR。 11      * 為此,該類將重寫基類型的 VisitBinary 方法,這是因為條件 AND 表達式表示為二元表達式。12      * 在 VisitBinary 方法中,如果傳遞到該方法的表達式表示條件 AND 運算,13      * 代碼將構造一個包含條件 OR 運算符(而不是條件 AND 運算符)的新表達式。 14      * 如果傳遞到 VisitBinary 的表達式不表示條件 AND 運算,則該方法交由基類實現(xiàn)來處理。15      * 基類方法構造類似于傳入的表達式樹的節(jié)點,但這些節(jié)點將其子目錄樹替換為訪問器遞歸生成的表達式樹。*/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                 //修改AndAlse為OrElse29                 return Expression.MakeBinary(ExpressionType.OrElse, left, right, node.IsLiftedToNull, node.Method);30             }31             return base.VisitBinary(node);32         }33     }34 }

測試代碼

 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             //修改前 9             Console.WriteLine(expr);10             AndAlsoModifier treeModifier = new AndAlsoModifier();11             Expression modifiedExpr = treeModifier.Modify((Expression)expr);12             //修改后13             Console.WriteLine(modifiedExpr);14             Console.Read();15         }16     }17 }

輸出結果

小結:修改表達式樹,需繼承ExpressionVisitor類,并重寫它的VisitBinary(如果是類似AND這類的二元表達式)方法。再舉一個例子,如果要將大于修改為小于等于,可修改VisitBinary方法的實現(xiàn)。

 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                 //修改> 為<= 8                 return Expression.MakeBinary(ExpressionType.LessThanOrEqual, left, right, node.IsLiftedToNull, node.Method); 9             }10             return base.VisitBinary(node);11         }

結果

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 公主岭市| 西城区| 昌都县| 友谊县| 会同县| 巴林右旗| 益阳市| 婺源县| 仙桃市| 松溪县| 应城市| 运城市| 肇源县| 广平县| 甘泉县| 宜丰县| 文化| 邵武市| 遂昌县| 景德镇市| 布拖县| 盐城市| 城步| 海口市| 墨江| 宁蒗| 徐汇区| 鱼台县| 青河县| 鄱阳县| 汉阴县| 化德县| 河南省| 兴安盟| 泾源县| 和平区| 天柱县| 章丘市| 天峨县| 吴忠市| 张家口市|