執行表達式樹 本節主要展示如何去執行表達式樹。運行一個可能含有返回值或只是執行一個操作,比如方法調用的表達式樹。 只有表示lambda表達式的表達式樹能夠被執行。它是一個 "LambdaExpression" 或 "Expression" 類型。為了執行這些表達式樹,調用 "Compile" 方法來 ...
執行表達式樹
本節主要展示如何去執行表達式樹。運行一個可能含有返回值或只是執行一個操作,比如方法調用的表達式樹。
只有表示lambda表達式的表達式樹能夠被執行。它是一個 LambdaExpression 或 Expression
註意:
如果這個委托的類型是未知的,那麼這個委托的類型是LambdaExpression而不是Expression
,你必須調用委托的 DynamicInvoke 方法而不是直接調用Invoke。
如果一個表達式樹不代表一個lambda表達式,你可以創建一個新的表達式樹將原來的表達式樹來作為它的Body,通過調用 Lambda(Expression, IEnumerable) 方法。然後你就可以調用這個lambda表達式了
Example
下麵的代碼說明如何運行一個表示一個數的冪運算的表達式樹通過生成lambda並調用它。結果是顯示這個數的平方
//執行表達式樹
BinaryExpression be = Expression.Power(Expression.Constant(2D), Expression.Constant(3D));
//創建一個委托表達式
Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);
// 編譯lambda表達式
Func<double> compiledExpression = le.Compile();
//執行lambda表達式
double result = compiledExpression();
//顯示值
Console.WriteLine(result);
編譯的代碼
- 添加項目引用 System.Core.dll
- 添加命名空間 System.Linq.Expressions
如何修改表達式樹
這節主要展示怎樣去修改表達式樹。表達式樹是不可變的(Immutable),意味著它不能被直接修改。為了修改表達式樹,那麼你必須新建一個已經存在的表達式樹的副本,併在創建副本時進行所需的更改。你可以使用 ExpressionVisitor 類去解析表達式樹並複製它訪問的每一個節點。
修改表達式樹
新建控制台應用程式
添加引用
System.Linq.Expressions
在你的項目中添加類
AndAlsoModifier
```c#
public class AndAlsoModifier : 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);
//讓二元運算符OrElse代替AndAlso
return Expression.MakeBinary(ExpressionType.OrElse, left, right, b.IsLiftedToNull, b.Method);
}
return base.VisitBinary(b);
}
}
```
這個類繼承了 ExpressionVisitor 而且專門用來修改表示條件 And
操作的表達式。它改變從 And
條件到 OR
。為了這個目的, AndAlsoModifier
重寫了基類的 VisitBinary 方法,因為 And
表示的是一個二元表達式。在 VisitBinary
方法中,如果這個表達式傳遞的是 And
操作,代碼會構造一個包含條件操作 OR
新的表達式而不是 And
。如果表達式傳給 VisitBinary
的不是 And
操作,那麼方法就會優先基類的實現。它基類的方法構造一個節點就像傳遞進來的表達式樹一樣,但是這個節點有它們的子樹,被訪問者遞歸生成的表達式樹替換。
添加引用
System.Linq.Expressions
在 Program.cs 文件添加 Main 方法並並創建一個表達式樹傳遞給這個方法來修改它。
```c#
Expression
Console.WriteLine(expr);
AndAlsoModifier treeModifier = new AndAlsoModifier();
Expression modifiedExpr = treeModifier.Modify((Expression) expr);
Console.WriteLine(modifiedExpr);
/* This code produces the following output:
name => ((name.Length > 10) && name.StartsWith("G"))
name => ((name.Length > 10) || name.StartsWith("G"))
*/
```
這段代碼創建了一個包含 And
操作的表達式樹。然後新建一個 AndAlsoModifier
的實例並給方法 Modify
傳遞之前創建的表達式樹。並輸出原始和修改後的表達式樹顯示差異。
- 編譯並運行程式。