说说表明式树,表达式树

By admin in 4858.com on 2019年4月11日

C# 知识回看 – 表明式树 Expression Trees

 

C# 知识回想 – 表明式树 Expression Trees

 

[C#] 说说表明式树,

表明式树(Expression Trees)

2018-01-08 1九:00 by 沉睡的木木夕, 6玖 阅读, 一 评论, 收藏, 编辑

目录

  • 简介
  • Lambda
    表明式创造表达式树
  • API
    成立表明式树
  • 浅析表明式树
  • 发布式树的永久性
  • 编写翻译表明式树
  • 执行表明式树
  • 修改表明式树
  • 调试

 

目录

  • 简介
  • Lambda
    表明式创设表明式树
  • API
    成立表明式树
  • 剖析表明式树
  • 发挥式树的永久性
  • 编写翻译表明式树
  • 进行表明式树
  • 修改表明式树
  • 调试

 

说说表明式树 – Expression Trees

[翻译]表明式树(Expression Trees)

*原来的文章地址:

表明式树显示的是代码的树形结构,每多个节点都以一个表明式,例如:调用3个方法可能调用一个2元运算表明式比如 x < y

您可以透过表达式树来编写翻译和运作代码。那表示能动态修改运营的代码,就好比在数据库中运营LINQ以七个变量的花样查询数据和创立四个动态的询问语句。关于表达式树在LINQ的越来越多使用消息详见How
to: Use Expression Trees to Build Dynamic Queries
(C#).

表明式树也被用于DL昂科拉(动态语言运转时),提供DLLAND与.NET
Framework之间的互操作性,使编写翻译器解析(Emit)表达式树,而不是MSIL。关于DLRAV四越来越多音信详细详见说说表明式树,表达式树。Dynamic
Language Runtime
Overview.

您能够用C#/VB编写翻译器在您的lambda表明式变量的底蕴上生成三个表达式树,大概您可以经过行使在System.Linq.Expressions取名空间创造表明式树.

简介

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

  你能够对表明式树中的代码进行编写制定和平运动算。那样能够动态修改可进行代码、在分歧数据库中实践
LINQ 查询以及开创动态查询。 

  表明式树还是能用于动态语言运维时 (DL翼虎)
以提供动态语言和 .NET Framework 之间的互操作性。 

 

简介

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

  你能够对表明式树中的代码实行编辑和平运动算。那样能够动态修改可实施代码、在差别数据库中履行
LINQ 查询以及开创动态查询。 

  表明式树还能够用来动态语言运维时 (DL卡宴)
以提供动态语言和 .NET Framework 之间的互操作性。 

 

  简单说下发挥式树。

 

从拉姆da表明式创设表明式树

当3个lambda表明式被分配到品种为Expression的的二个变量时,编写翻译器会分析生成代码创建一个表明式树来代表那几个lambda
.

C#编写翻译器能从lambda生成表明式树(可能从四个单行的lambda)。但它不可能转换来lambda评释(或多行lambda)。越多关于lambda音信见Lambda
Expressions.

4858.com ,上边包车型地铁代码例子说明了哪些用C#来生成四个表达式树来表示叁个lambda表达式: num => num < 5

Expression<Func<int, bool>> lambda = num => num < 5;

1、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;

 

壹、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那一个类来创立表明式树。那几个类包涵了创建钦赐项目表明式树节点的静态工厂方法,例如, ParameterExpression它表示三个参数可能变量,又如MethodCallExpression,它意味着3个措施调用。ParameterExpression, MethodCallExpression以及其它的内定项指标表明式树都在System.Linq.Expressions取名空间下。那几个类都连任自 Expression抽象类.

上面包车型大巴代码展现如何用API创立表达式树来代表贰个lambda表明式num => num < 5

// 在你的代码文件添加引用:  
// using System.Linq.Expressions;  

// 为lambda表达式num => num < 5手动生成表达式树   
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");  
ConstantExpression five = Expression.Constant(5, typeof(int));  
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);  
Expression<Func<int, bool>> lambda1 =  
    Expression.Lambda<Func<int, bool>>(  
        numLessThanFive,  
        new ParameterExpression[] { numParam }); 

在.NET
Framework四.0后头,表明式树API也支撑分配和操纵流表明式,例如循环,条件判断块以及极度捕捉块(try-catch)。通过API,你能够创设比编写翻译器通过从lambda表明式创设的更为扑朔迷离的表述式树。下边包车型大巴这一个例子显示了怎么样创制3个表明式树来表示2个数的阶乘(factorial
of number).

//创建一个参数表达式
ParameterExpression value = Expression.Parameter(typeof(int), "value");
//创建一个表达式表示本地变量
ParameterExpression result = Expression.Parameter(typeof(int), "result");
//创建标签从循环跳到指定标签
LabelTarget label = Expression.Label(typeof(int));
//创建方法体
BlockExpression block = Expression.Block(
    //添加本地变量
    new[] { result },
    //为本地变量赋值一个常量
    Expression.Assign(result, Expression.Constant(1)),
    //循环
    Expression.Loop(
        //添加循环条件
        Expression.IfThenElse(
            //条件:value > 1
            Expression.GreaterThan(value, Expression.Constant(1)),
            //if true
            Expression.MultiplyAssign(result, Expression.PostDecrementAssign(value)),
            //if false
            Expression.Break(label, result)
            ),
        label
        )
    );

int facotorial = Expression.Lambda<Func<int, int>>(block, value).Compile()(5);  
Console.WriteLine(factorial);  
// 输出 120.  

越来越多关于详见Generating Dynamic Methods with Expression Trees in Visual
Studio
2010,也支撑后续VS版本.

贰、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 类的静态方法举办创办。

 

2、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 类的静态方法实行创办。

 

介绍

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

  你能够对表明式树中的代码进行编写制定和平运动算。那样能够动态修改可实行代码、在不一致数据库中履行
LINQ 查询以及开创动态查询。 

  表达式树还能够用于动态语言运维时 (DLENCORE) 以提供动态语言和 .NET Framework
之间的互操作性,同时确认保障编写翻译器编写员能够发射表明式树而非 Microsoft
中间语言 (MSIL)。 

 

解析表达式树(Parsing Expression Trees)

上边包车型客车代码示例演示了怎么将表达式树表示为lambda表达式num => num < 5,能够被解释为局地。

public void DecomposedExpressionTrees()
{
    //创建一个表达式树
    Expression<Func<int, bool>> exprTree = num => num < 5;
    //分解表达式
    ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
    //num < 5
    BinaryExpression operation = (BinaryExpression)exprTree.Body;
    ParameterExpression left = (ParameterExpression)operation.Left;
    ConstantExpression right = (ConstantExpression)operation.Right;

    Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
            param.Name, left.Name, operation.NodeType, right.Value);
}

3、解析表明式树 

   下列代码示例展现怎样解释表示 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}");

4858.com 1

 

 

 

叁、解析表明式树 

   下列代码示例显示什么解释表示 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}");

4858.com 2

 

 

 

1、依据 拉姆da 表明式成立表明式树

  若 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;

 

发挥式树的不变性(Immutability of Expression Trees)

表明式树应该是不可变的。那象征若是你想修改表明式树,那么您不可能不重新已经存在的协会表明式树并替换其某个节点。你能够选拔表明式树访问器(ExpressionVisitor)遍历表明式树。愈来愈多那方面新闻详见How
to: Modify Expression Trees
(C#).

四、表达式树永久性

  表明式树应享有永久性(类似字符串)。那代表一旦您想修改某些表明式树,则必须复制该表达式树然后替换当中的节点来成立三个新的抒发式树。  你能够动用表明式树访问者遍历现有表达式树。第拾节介绍了怎么修改表明式树。

 

四、表明式树永久性

  表明式树应怀有永久性(类似字符串)。那意味1旦您想修改某些表明式树,则必须复制该表明式树然后替换在那之中的节点来创建2个新的发表式树。  你能够利用表明式树访问者遍历现有表明式树。第拾节介绍了什么样修改表明式树。

 

二、通过 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 类的静态方法实行创办。

 

编写翻译表明式树

泛型 Expression 类型提供一个 Compile主意来将表明式树所表示的代码编写翻译成可实施的嘱托。

上面那段代码展现怎么编写翻译表明式树和平运动转结果代码

public void ComplieExpressTrees()
{
    //创建一个表达式树
    Expression<Func<int, bool>> expr = num => num < 5;
    //编译表达式树为委托
    Func<int, bool> result = expr.Compile();
    //调用委托并写结果到控制台
    Console.WriteLine(result(4));

    //也可以使用简单的语法来编译运行表达式树
    Console.WriteLine(expr.Compile()(4));
    //结果一样
}

更加多关于怎么样运作表明式树音讯,详见How to: Execute Expression Trees
(C#).

愿意有个生活理想的主次人生

 

 

 

本节任重先生而道远展现什么去履行表明式树。运维1个大概包罗再次来到值或只是实施三个操作,比如方法调用的表明式树。

只有表示lambda表达式的表明式树能够被实践。它是3个 LambdaExpression 或 Expression 类型。为了施行这个表明式树,调用 Compile 方法来生成贰个可实施的寄托并调用它。

注意:

假设这几个委托的连串是未知的,那么那么些委托的品类是拉姆daExpression而不是Expression,你必须调用委托的 DynamicInvoke主意而不是一贯调用Invoke。

若果二个表明式树不代表一个lambda表明式,你能够成立贰个新的表明式树将原先的表明式树来作为它的Body,通过调用 Lambda(Expression,
IEnumerable) 方法。然后您就足以调用那几个lambda表明式了

5、编写翻译表达式树

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

4858.com 3

 

 

 

 

5、编写翻译表明式树

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

4858.com 4

 

 

 

 

 3、解析表明式树 

   下列代码示例显示什么分排毒示 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<Func<string, int>>
funcExpression = msg => msg.Length; 三 //表达式树编写翻译成委托 四 var
lambda = funcExpression.Compile(); 五 //调用委托 6Console.WriteLine(lambda(“Hello, World!”)); 柒 八 //语法简化 9Console.WriteLine(funcExpression.Compile()(“Hello, World!”));

一 const int n = 一; 贰 const int m = 二; 3 肆 //待执行的表达式树 5BinaryExpression 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(); 拾 11 //执行
lambda 表明式 12 Console.WriteLine($”{n} + {m} = {func()}”);

4858.com 5

 

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);

陆、执行表明式树

  执行表明式树大概会再次回到二个值,也说不定仅执行七个操作(例如调用方法)。

  只好进行代表 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()}");

4858.com 6

 

6、执行表明式树

  执行表明式树或许会重临二个值,也说不定仅执行八个操作(例如调用方法)。

  只好执行代表 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()}");

4858.com 7

 

柒、怎样:修改表明式树 

   该类继承 ExpressionVisitor 类,并且专用于修改意味着原则 AND 运算的说明式。它将这么些运算从原则 AND 更改为条件 OR。为此,该类将重写基类型的 VisitBinary 方法,那是因为口径 AND 表明式表示为二元表明式。在 VisitBinary 方法中,如若传递到该格局的表明式表示原则AND 运算,代码将组织3个分包条件 OR 运算符(而不是规则 AND 运算符)的新表达式。假设传递到 VisitBinary 的表达式不意味着原则 AND运算,则该方式交由基类完结来处理。  基类方法协会类似于传播的表述式树的节点,但这几个节点将其子目录树替换为访问器递归生成的抒发式树。
 

 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     }

4858.com 8

 

 


【原作链接】 

 

预览版,更新于09/16

 

  

] 说说表明式树, 说说表达式树 – Expression
Trees 序 不难说下发布式树。 目录 介绍
表明式树以树形数据结构表示代码,当中每三个节点都…

编写翻译的代码

  • 加上项目引用 System.Core.dll
  • 添加命名空间 System.Linq.Expressions

七、修改表明式树 

   该类继承 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     }

4858.com 9

 

 

 

柒、修改表明式树 

   该类继承 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     }

4858.com 10

 

 

 

怎么样修改表明式树

那节首要显示什么去修改表明式树。表明式树是不可变的(Immutable),意味着它不可能被直接修改。为了修改表达式树,那么您不可能不新建一个一度存在的宣布式树的副本,并在成立副本时举行所需的变更。你能够应用 ExpressionVisitor 类去分析表达式树并复制它访问的每七个节点。

八、调试

  八.1 参数表明式

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

4858.com 11

图8-1

4858.com 12

图8-2

   从 DebugView
可见,假若参数没盛名称,则会为其分配3个自动生成的称谓。

 

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

4858.com 13

图8-3

4858.com 14

图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);

4858.com 15

图8-5

4858.com 16

图8-6

   观望 DebugView ,假诺 lambda
表明式没闻名称,则会为其分配三个自动生成的称谓。

 

八、调试

  捌.一 参数表明式

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

4858.com 17

图8-1

4858.com 18

图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);

4858.com 19

图8-3

4858.com 20

图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);

4858.com 21

图8-5

4858.com 22

图8-6

   观看 DebugView ,假若 lambda
表明式没出名称,则会为其分配一个自动生成的称谓。

 

修改表明式树

  1. 新建控制台应用程序

  2. 丰盛引用 System.Linq.Expressions

  3. 在您的档次中添加类 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 表示的是三个2元表明式。在 VisitBinary 方法中,如若这些表明式传递的是 And 操作,代码会协会二个暗含条件操作 OR 新的表明式而不是 And。假使表达式传给 VisitBinary 的不是 And 操作,那么方法就会预先基类的实现。它基类的艺术协会一个节点就像是传递进入的表明式树1样,不过这么些节点有它们的子树,被访问者递归生成的表明式树替换。

  1. 加上引用 System.Linq.Expressions

  2. 在 Program.cs 文件添加 Main
    方法并并创造一个表明式树传递给这么些主意来修改它。

“`c#
Expression<func<string, bool=””>> expr = name =>
name.Length > 10 && name.StartsWith(“G”);
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 传递在此以前创制的表明式树。并出口原始和改动后的表明式树显示差别。

  1. 编写翻译并运营程序。

瞩望有个生活不错的次序人生

 

表明式树(Expression
Trees)

 

 

 

 


【原来的书文链接】 

 

 


【原作链接】 

【参考】微软官方文书档案

 

 

【参考】微软官方文书档案

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有