NET(C#):使用Expression Tree構建帶有參數、本地變量和返回值的Lambda

.NET(C#):使用Expression Tree構建帶有參數、本地變量和返回值的Lambda

對於參數,需要使用Expression.Parameter創建ParameterExpression對象,注意需要在創建Lambda時傳入ParameterExpression數組纔可以使參數有效。

對於本地變量,首先Expression類型提供Variable方法,但是這個Variable方法返回的也是ParameterExpression,實際上他們內部創建的都是同一種ParameterExpression對象,唯一的區別是Parameter方法會考慮Type.IsByRef的情況,但是Variable會拋出異常(如果Type.IsByRef爲True)。其次需要注意的是,局部變量需要在創建BlockExpression時以ParameterExpression數組的方式傳入。

對於返回值,需要先通過Expression.Label的部分重載創建LabelTarget對象,接着通過Expression的Return方法(間接調用MakeGoto)返回GotoExpression,注意是和一個LabelTarget對象相關聯的。最後用Expression.Label的另一部分返回LabelExpression的重載創建Label表達式,也就是Label在代碼塊中的具體位置。最後LabelTarget對象可以按照類型標記,也可以按照類型連同名稱標記。

 

下面代碼,我們要創建一個和如下方法類似的Lambda:

static string doo(int i)
{
   string str = i.ToString();
   return str;
}

 

全部代碼:

//+ using System.Reflection;
//+ using System.Linq.Expressions;

//參數
var pa = Expression.Parameter(typeof(int), "i");
//本地變量
var loc = Expression.Variable(typeof(string), "str");
//創建LabelTarget用來返回值
LabelTarget labelTarget = Expression.Label(typeof(string));

//調用i.ToString()
MethodCallExpression med = Expression.Call(pa, typeof(object).GetMethod("ToString", new Type[] { }));
//將結果賦值給本地字符串變量
BinaryExpression asn = Expression.Assign(loc, med);
//創建返回表達式(實際上就是Goto表達式)
GotoExpression ret = Expression.Return(labelTarget, loc);
//創建返回表達式的目標Label
LabelExpression lbl = Expression.Label(labelTarget, Expression.Constant(String.Empty));
//生成BlockExpression
BlockExpression blocks = Expression.Block(
   new ParameterExpression[] { loc },
   asn,
   ret,
   lbl);
//生成Lambda表達式
Expression<Func<int, string>> lam = Expression.Lambda<Func<int, string>>(blocks,
   new ParameterExpression[] { pa });
//運行並輸出結果
Func<int, string> del = lam.Compile();
Console.WriteLine(del(17));

 

輸出:

17

Related Posts:

  1. .NET(C#):methodof、fieldof和ldtoken

  2. .NET(C#): Task.Unwrap擴展方法和async Lambda

  3. 使用Html Agility Pack 1.4解析HTML的DOM Tree

  4. .NET(C#):分析IL中的if-else,while和for語句並用Emit實


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章