寫在前面
系列文章
Expression
表達式樹創建方式
一個例子
總結
上篇文章介紹了擴展方法,這篇文章開始將陸續介紹在linq中使用最多的表達式樹的相關概念,以概念及例子一一列出如何在代碼中使用Expression。
Linq之Lambda表達式初步認識
Linq之Lambda進階
Linq之隱式類型、自動屬性、初始化器、匿名類
Linq之擴展方法
還是老樣子,首先看MSDN中對表達式樹的描述
表達式樹以樹形數據結構表示代碼,其中每一個節點都是一種表達式,比如方法調用和 x < y 這樣的二元運算等。
你可以對表達式樹中的代碼進行編輯和運算。 這樣能夠動態修改可執行代碼、在不同數據庫中執行 LINQ 查詢以及創建動態查詢。
表達式樹又稱為“表達式目錄樹”,以數據形式表示語言級代碼,它是一種抽象語法樹或者說是一種數據結構。
通過上面的描述,你會發現表達式樹的作用:動態修改可執行代碼、在不同數據庫中執行Linq查詢及創建動態查詢。那它是如何做到的呢?那下面就開始咱們的表達式樹之旅吧。
表達式樹創建方式分為兩種:以lambda表達式的方式創建,通過API靜態方法創建。
若 lambda 表達式被分配給 Expression<TDelegate> 類型的變量,則編譯器可以發射代碼以創建表示該 lambda 表達式的表達式樹。
看一個例子:

1 static void Main(string[] args)2 {3 System.Linq.Expressions.Expression<Func<int, bool>> lambda = num => num >= 5;4 }上面的代碼意思就以表達式目錄樹的形式將強類型的lambda表達式num=>num>=5標識為數據結構。
通過 API 創建表達式樹需要使用 Expression 類。
該類包含創建特定類型表達式樹節點的靜態工廠方法,比如表示參數變量的 ParameterExpression,或者是表示方法調用的 MethodCallExpression。 System.Linq.Expressions 名稱空間還解釋了 ParameterExpression、MethodCallExpression和另一種具體表達式類型。 這些類型來源于抽象類型 Expression。
那么我使用API的方式創建上面例子中的表達式樹:
說的很高大上,其實就是類Expression的一系列靜態方法。
首先引入命名空間
using System.Linq.Expressions;
1 static void Main(string[] args) 2 { 3 //創建lambda表達式 num=>num>=5 4 //第一步創建輸入參數,參數名為num,類型為int類型 5 ParameterExpression numParameter = Expression.Parameter(typeof(int), "num"); 6 //第二步創建常量表達式5,類型int 7 ConstantExpression constant = Expression.Constant(5, typeof(int)); 8 //第三步創建比較運算符>=,大于等于,并將輸入參數表達式和常量表達式輸入 9 //表示包含二元運算符的表達式。BinaryExpression繼承自Expression10 BinaryExpression greaterThanOrEqual = Expression.GreaterThanOrEqual(numParameter, constant);11 //第四步構建lambda表達式樹12 //Expression.Lambda<Func<int, bool>>:通過先構造一個委托類型來創建一個 LambdaExpression13 Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(greaterThanOrEqual, numParameter);14 }
通過上面的代碼你會發現這種方式在創建的時候,lambda表達式的左右及二元運算符都要分別的創建,然后在通過Expression.Lambda方法構建lambda表達式。
在 .NET Framework 4 中,API 表達式樹還支持賦值表達式和控制流表達式,比如循環、條件塊和 try-catch 塊等。
看一個例子,通過API表達式樹創建一個利用循環求1到n的和的表達式樹。
如果能這樣寫該有多好啊
1 Expression<Func<int, int>> lambda = n =>2 {3 int result = 0;4 for (int j = n; j >= 0; j--)5 {6 result += j;7 }8 return result;9 };可惜

通過API創建表達式樹,可以創建更為復雜的表達式樹,這里先嘗嘗鮮
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //變量表達式 6 ParameterExpression i = Expression.Variable(typeof(int), "i"); 7 //變量表達式 8 ParameterExpression sum = Expression.Variable(typeof(int), "sum"); 9 //跳出循環標志10 LabelTarget label = Expression.Label(typeof(int));11 //塊表達式12 BlockExpression block =13 Expression.Block(14 //添加局部變量15 new[] { sum },16 //為sum賦初值 sum=117 //Assign表示賦值運算符18 Expression.Assign(sum, Expression.Constant(1, typeof(int))),19 //loop循環20 Expression.Loop(21 //如果為true 然后求和,否則跳出循環22 Expression.IfThenElse(23 //如果i>=024 Expression.GreaterThanOrEqual(i, Expression.Constant(0, typeof(int))),25 //sum=sum+i;i++;26 Expression.AddAssign(sum, Expression.PostDecrementAssign(i)),27 //跳出循環28 Expression.Break(label, sum)29 ), label30 ) // Loop ends31 );32 int resutl = Expression.Lambda<Func<int, int>>(block, i).Compile()(100);33 Console.WriteLine(resutl);34 Console.Read();35 }36 }輸出結果

本篇文章主要介紹了表達式樹的概念及兩種創建方式。在文章的結尾給出了一個例子,也是先嘗嘗鮮,對于代碼中的一些靜態方法可先參考注釋。下篇文章將介紹一些Expression的常用的靜態方法。
參考文章
http://msdn.microsoft.com/zh-cn/library/bb397951.aspx
新聞熱點
疑難解答