• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C# 表达式树Expression Trees的知识梳理

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

作者:反骨仔(二五仔) 字体:[增加 减小] 来源:互联网 时间:2017-05-28

反骨仔(二五仔) 通过本文主要向大家介绍了等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

目录

  • 简介
  • Lambda 表达式创建表达式树
  • API 创建表达式树
  • 解析表达式树
  • 表达式树的永久性
  • 编译表达式树
  • 执行表达式树
  • 修改表达式树
  • 调试

简介

表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。

你可以对表达式树中的代码进行编辑和运算。这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。

表达式树还能用于动态语言运行时 (DLR) 以提供动态语言和 .NET Framework 之间的互操作性。

一、Lambda 表达式创建表达式树

若 lambda 表达式被分配给 Expression<TDelegate> 类型的变量,则编译器可以发射代码以创建表示该 lambda 表达式的表达式树。 

C# 编译器只能从表达式 lambda (或单行 lambda)生成表达式树。

下列代码示例使用关键字 Expression创建表示 lambda 表达式:

 Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
 Expression<Func<int, bool>> funcExpression1 = (n) => n < 0;
 Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == 0;
</div>

二、API 创建表达式树

通过 API 创建表达式树需要使用Expression 类

下列代码示例展示如何通过 API 创建表示 lambda 表达式:num => num == 0

//通过 Expression 类创建表达式树
 // lambda:num => num == 0
 ParameterExpression pExpression = Expression.Parameter(typeof(int)); //参数:num
 ConstantExpression cExpression = Expression.Constant(0); //常量:0
 BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); //表达式:num == 0
 Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda 表达式:num => num == 0
</div>

代码使用Expression 类的静态方法进行创建。

三、解析表达式树

下列代码示例展示如何分解表示 lambda 表达式 num => num == 0 的表达式树。

Expression<Func<int, bool>> funcExpression = num => num == 0;
 //开始解析
 ParameterExpression pExpression = funcExpression.Parameters[0]; //lambda 表达式参数
 BinaryExpression body = (BinaryExpression)funcExpression.Body; //lambda 表达式主体:num == 0
 Console.WriteLine($"解析:{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");
</div>

四、表达式树永久性

表达式树应具有永久性(类似字符串)。这意味着如果你想修改某个表达式树,则必须复制该表达式树然后替换其中的节点来创建一个新的表达式树。  你可以使用表达式树访问者遍历现有表达式树。第七节介绍了如何修改表达式树。

五、编译表达式树

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!"));
</div>

六、执行表达式树

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

只能执行表示 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()}");
</div>

七、修改表达式树

该类继承 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);
 }
 }
 }
</div>

八、调试

8.1 参数表达式

 ParameterExpression pExpression1 = Expression.Parameter(typeof(string));
 ParameterExpression pExpression2 = Expression.Parameter(typeof(string), "msg");
</div>

图8-1

图8-2

从 DebugView 可知,如果参数没有名称,则会为其分配一个自动生成的名称。

 const int num1 = 250;
 const float num2 = 250;
 ConstantExpression cExpression1 = Expression.Constant(num1);
 ConstantExpression cExpression2 = Expression.Constant(num2);
</div>

图8-3

图8-

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2017-05-28C#给picturebox控件加图片选中状态的2个方法
  • 2017-05-28unity3d调用手机或电脑摄像头
  • 2017-05-28C#+MO实现一个道路编辑软件(刚开始)
  • 2017-05-28C#枚举中的位运算权限分配浅谈
  • 2017-05-28时间字符串转换成日期对象datetime的方法
  • 2017-05-28C#获取USB事件API实例分析
  • 2017-05-28C#中把任意类型的泛型集合转换成SQLXML数据格式的实例
  • 2017-05-28C#中 const 和 readonly 的不同
  • 2017-05-28C#数字图象处理之图像灰度化方法
  • 2017-05-28C#启动进程的几种常用方法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C#操作DataTable方法实现过滤、取前N条数据及获取指定列数据列表的方法
    • 简单了解C#设计模式编程中的桥接模式
    • C#切换鼠标左右键习惯无需控制面板中修改
    • C# 批处理调用方法
    • 学会使用C#异常
    • 操作XML文档遇到的XMLNS问题及解决方法 (C# 和 PHP)
    • C#中new的用法及与override的区别分析
    • WinForm窗体间传值的方法
    • 解析C#中的ref和out参数
    • C#中Predicate<T>与Func<T, bool>泛型委托的用法实例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有