[Expression Tree] MSDN學習系列 1-運算式樹狀架構
什麼是Expression Tree?
就是將程式碼當作樹狀結構的資料,並可以動態修改Runtime的程式碼、動態查詢及取得程式碼中的相關資訊。
練習第一個Expresssion Tree
以下為Lambda運算式並宣告一個泛型委派的變數來接,表示為傳入一個num參數,並回傳布林值,在執行只要視為一個方法來叫用即可lambda(100)
Func<int, bool> lambda = num => num < 5;同樣的Lambda運算式!若宣告一個Expression變數來接,則可以取出此運算式的相關資訊,如下取出參數、常數、二元運算式等資訊,最後再透過compiler方法建置成泛型委派來執行。
Expression<Func<int, bool>> lambda = num => num > 10;
Console.WriteLine(lambda.Body);//運算式主體 n*n
Console.WriteLine(lambda.Parameters[0]);//參數
Console.WriteLine(lambda.NodeType);//節點型別
Console.WriteLine(lambda.ReturnType);//回傳型別
Console.WriteLine(lambda.Compile()(10));//建置後執行
顯示結果
透過Expression API動態建立一個簡單運算式
在上面例子是將已建立的Lambda運算式去透過Expression去取得,而我們也可以透過Expression所以提供的工廠方法去建立一個Lambda運算式來使用
ParameterExpression num = Expression.Parameter(typeof(int), "n");
Expression<Func<int, int>> expr =
Expression<Func<int, int>>.Lambda<Func<int, int>>(//建立Lambda方法
Expression.Multiply(num, num)//建立一個num*num的主體
, new ParameterExpression[] { num }//此主體方法為傳入一個num參數
);
Console.WriteLine(expr.Body);
Console.WriteLine(expr.Parameters[0]);
Console.WriteLine(expr.NodeType);
Console.WriteLine(expr.ReturnType);
Console.WriteLine(expr.Compile()(10));
顯示結果
透過Expression API動態建立判斷式、迴圈區塊的運算式
ParameterExpression value = Expression.Parameter(typeof(int), "value");
ParameterExpression result = Expression.Parameter(typeof(int), "result");
LabelTarget label = Expression.Label(typeof(int));
BlockExpression block = Expression.Block(//建立方法區塊
new[] { result },//指定方法的參數為result
Expression.Assign(result, Expression.Constant(1)),//設定變數result=1
Expression.Loop(//建立Loop迴圈區塊
Expression.IfThenElse(//建立判斷式區塊
Expression.GreaterThan(value, Expression.Constant(1)),//條件:參數大於5
Expression.MultiplyAssign(result, Expression.PostDecrementAssign(value)),//true:執行乘法運算並將結果給result 例:result*=value
Expression.Break(label, result)//false:跳離Loop並到下方的label
)
, label//指定標籤,讓上方的Break跳到此行用
)
);
var lamba = Expression.Lambda<Func<int, int>>(block, value);//將方法區塊指定成Lamdba運算式
int factorial = lamba.Compile()(5);
Console.WriteLine(lamba);
Console.WriteLine(factorial);
輸出結果:120
使用DebugView查看ExpressionTree的內容執行結果
在撰寫Expression時若不確定寫的是否正確,可以在Debug時查看展開後的運算式內容
參考資料
http://msdn.microsoft.com/zh-tw/library/bb397951.aspx
第二篇....待續