Expression Trees

只是想简单说下表达式树 - Expression Trees

目录

简介

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

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

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

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

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

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

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

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

二、API 创建表达式树

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

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

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

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

三、解析表达式树

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

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

四、表达式树永久性

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

五、编译表达式树

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

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

六、执行表达式树

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

  只能执行表示 lambda 表达式的表达式树。表示 lambda 表达式的表达式树属于 LambdaExpression 或 Expression<TDelegate> 类型。若要执行这些表达式树,需要调用 Compile 方法来创建一个可执行委托,然后调用该委托。
 1             const int n = 1;
2 const int m = 2;
3
4 //待执行的表达式树
5 BinaryExpression bExpression = Expression.Add(Expression.Constant(n), Expression.Constant(m));
6 //创建 lambda 表达式
7 Expression<Func<int>> funcExpression = Expression.Lambda<Func<int>>(bExpression);
8 //编译 lambda 表达式
9 Func<int> func = funcExpression.Compile();
10
11 //执行 lambda 表达式
12 Console.WriteLine($"{n} + {m} = {func()}");

七、修改表达式树

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

 1     internal class Program
2 {
3 private static void Main(string[] args)
4 {
5 Expression<Func<int, bool>> funcExpression = num => num == 0;
6 Console.WriteLine($"Source: {funcExpression}");
7
8 var visitor = new NotEqualExpressionVisitor();
9 var expression = visitor.Visit(funcExpression);
10
11 Console.WriteLine($"Modify: {expression}");
12
13 Console.Read();
14 }
15
16 /// <summary>
17 /// 不等表达式树访问器
18 /// </summary>
19 public class NotEqualExpressionVisitor : ExpressionVisitor
20 {
21 public Expression Visit(BinaryExpression node)
22 {
23 return VisitBinary(node);
24 }
25
26 protected override Expression VisitBinary(BinaryExpression node)
27 {
28 return node.NodeType == ExpressionType.Equal
29 ? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //重新弄个表达式:用 != 代替 ==
30 : base.VisitBinary(node);
31 }
32 }
33 }

八、调试

  8.1 参数表达式

1             ParameterExpression pExpression1 = Expression.Parameter(typeof(string));
2 ParameterExpression pExpression2 = Expression.Parameter(typeof(string), "msg");

图8-1

图8-2

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

1             const int num1 = 250;
2 const float num2 = 250;
3
4 ConstantExpression cExpression1 = Expression.Constant(num1);
5 ConstantExpression cExpression2 = Expression.Constant(num2);

图8-3

图8-4

  从 DebugView 可知,float 比 int 多了个后缀 F。

1             Expression lambda1 = Expression.Lambda<Func<int>>(Expression.Constant(250));
2 Expression lambda2 = Expression.Lambda<Func<int>>(Expression.Constant(250), "CustomName", null);

图8-5

图8-6

  观察 DebugView ,如果 lambda 表达式没有名称,则会为其分配一个自动生成的名称。


【原文链接】http://www.cnblogs.com/liqingwen/p/5868688.html

Expression Trees的更多相关文章

  1. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  2. Expression Trees 参数简化查询

    ASP.NET MVC 引入了 ModelBinder 技术,让我们可以在 Action 中以强类型参数的形式接收 Request 中的数据,极大的方便了我们的编程,提高了生产力.在查询 Action ...

  3. 表达式树(Expression Trees)

    [翻译]表达式树(Expression Trees) 原文地址:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/con ...

  4. ASP.NET MVC:Expression Trees 作为参数简化查询

    ASP.NET MVC 引入了 ModelBinder 技术,让我们可以在 Action 中以强类型参数的形式接收 Request 中的数据,极大的方便了我们的编程,提高了生产力.在查询 Action ...

  5. C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  6. Expression Trees (C# and Visual Basic)

    https://msdn.microsoft.com/en-us/library/bb397951.aspx Expression trees represent code in a tree-lik ...

  7. Expression Tree Basics 表达式树原理

    variable point to code variable expression tree data structure lamda expression anonymous function 原 ...

  8. 使用Expression做Linq的參數化排序

    Linq非常的好用,減少大量的資料庫操作手序,使用具名的類別,減少了在程式中寫SQL寫錯字的可能性,問題來了,如果我想用QueryString中的參數,作為排序的依據,但是因為是具名的類別,不能指定字 ...

  9. 不可不知的表达式树(1)Expression初探

    说起Lambda表达式,大家基本都很熟悉了,而表达式树(Expression Trees),则属于80%的工作中往往都用不到的那种技术,所以即便不是什么新技术,很多人对其理解都并不透彻.此文意图从表达 ...

随机推荐

  1. MySQL 5.7版本安装教程-踩坑总结

    下载 MySQL下载地址 选择下载64位(看自己电脑是32位还是64位) 点击下载之后,它会让你登录,没有Oracle账户,跟着它的步骤注册一个就好了. 安装 打开下载好的压缩包解压到你的某一目录下, ...

  2. java 实现 DES加密 解密算法

    DES算法的入口参数有三个:Key.Data.Mode.其中Key为8个字节共64位,是DES算法的工作密钥:Data也为8个字节64位,是要被加密或被解密的数据:Mode为DES的工作方式,有两种: ...

  3. winform设置DataGridView样式 (蓝色)

    本文转载:http://www.cnblogs.com/hailexuexi/archive/2012/04/23/2466398.html 代码: #region DataGridVeiw Styl ...

  4. Seeking USB Serial Com Port in Windows Automatically : via PID VID

    After you read previous article, you might know how to operate a com port in Windows.    But that ex ...

  5. 银行B2C直连

    银行B2C直连: 1. 银联B2C直连流程: 注: 所有银行B2C接入方式均为此流程. 不同银行只是签名及验签方式不一致,请求及返回参数不一样,其他的一致. 2. 银行B2C支付请求: 交易流程: ( ...

  6. hadoop处理Excel通话记录

    前面我们所写mr程序的输入都是文本文件,但真正工作中我们难免会碰到需要处理其它格式的情况,下面以处理excel数据为例 1.项目需求 有刘超与家庭成员之间的通话记录一份,存储在Excel文件中,如下面 ...

  7. HDU 4296 Buildings(贪心)

    题意: 给定n个建筑物,每个建筑物都有两个属性w, s,每个建筑物都有一个PDV = (Σw j)-s i .意思就是它上面的所有的w相加减去它的s,让求怎么放置这个建筑物使得每个建筑物当中PDV最大 ...

  8. 11.2 afternoon

    #include<iostream> #include<cstdio> #define ll long long using namespace std; ll n,ans; ...

  9. IIS注册.net框架及temp文件权限开放

    配置好IIS服务之后,在浏览器打开localhost:xx[端口号],提示:无法识别属性 targetFramework=4.0 这是因为项目是4.0框架,配置IIS时,在应用程序池没有选择.net ...

  10. 19、XHTML

    XHTML 可扩展超文本标签语言(EXtensible HyperText Markup Language). 是一种 W3C 标准. 更严格,更纯净的HTML代码. 目标是取代HTML代码. XHT ...