C# 表达式树Expression Trees的知识梳理

2019-12-30 15:44:02王旭

五、编译表达式树

Expression<TDelegate> 类型提供了 Compile 方法以将表达式树表示的代码编译成可执行委托。


//创建表达式树
 Expression<Func<string, int>> funcExpression = msg => msg.Length;
 //表达式树编译成委托
 var lambda = funcExpression.Compile();
 //调用委托
 Console.WriteLine(lambda("Hello, World!"));
 //语法简化
 Console.WriteLine(funcExpression.Compile()("Hello, World!"));

C#,表达式树

六、执行表达式树

执行表达式树可能会返回一个值,也可能仅执行一个操作(例如调用方法)。

只能执行表示 lambda 表达式的表达式树。表示 lambda 表达式的表达式树属于 LambdaExpression 或 Expression<TDelegate> 类型。若要执行这些表达式树,需要调用 Compile 方法来创建一个可执行委托,然后调用该委托。


const int n = 1;
 const int m = 2;
 //待执行的表达式树
 BinaryExpression bExpression = Expression.Add(Expression.Constant(n), Expression.Constant(m));
 //创建 lambda 表达式
 Expression<Func<int>> funcExpression = Expression.Lambda<Func<int>>(bExpression);
 //编译 lambda 表达式
 Func<int> func = funcExpression.Compile();
 //执行 lambda 表达式
 Console.WriteLine($"{n} + {m} = {func()}");

C#,表达式树

七、修改表达式树

该类继承 ExpressionVisitor 类,通过 Visit 方法间接调用 VisitBinary 方法将 != 替换成 ==。基类方法构造类似于传入的表达式树的节点,但这些节点将其子目录树替换为访问器递归生成的表达式树。 


internal class Program
 {
 private static void Main(string[] args)
 {
 Expression<Func<int, bool>> funcExpression = num => num == 0;
 Console.WriteLine($"Source: {funcExpression}");
 var visitor = new NotEqualExpressionVisitor();
 var expression = visitor.Visit(funcExpression);
 Console.WriteLine($"Modify: {expression}");
 Console.Read();
 }
 /// <summary>
 /// 不等表达式树访问器
 /// </summary>
 public class NotEqualExpressionVisitor : ExpressionVisitor
 {
 public Expression Visit(BinaryExpression node)
 {
 return VisitBinary(node);
 }
 protected override Expression VisitBinary(BinaryExpression node)
 {
 return node.NodeType == ExpressionType.Equal
  ? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //重新弄个表达式:用 != 代替 ==
  : base.VisitBinary(node);
 }
 }
 }

C#,表达式树