ibcadmin 发表于 2019-9-17 11:33:16

C# 表达式树讲解(一)

<h2>一、前言</h2>
<p>不绝想写一篇Dpper的定制化扩展的文章,但是内里会设计到对Lambda表达式的剖析,而剖析Lambda表达式,就必须要知道表达式树的相关知识点。我希望能通过对各个模块的知识点大概运用可以或很多一点的讲解,可以或许资助到园友相识得更多。固然讲解得不全面,如果能成为打开这块的一把钥匙,也是蜗牛比力欣慰的。</p>
<h2>二、表达树明确</h2>
<p>表达式树以树形数据布局表现代码,此中每一个节点都是一种表达式,它将我们原来可以直接由代码编写的逻辑以表达式的方式存储在树状的布局里,从而可以在运行时去剖析这个树,然后执行,实现动态的编辑和执行代码。在.Net 内里的Linq to SQL就是对表达式树的剖析。</p>
<p>这里先讲解下表达式和表达式树,表达式信赖大家都知道,好比x+5大概5,都可以算是表达式,而表达式树内里的树指的二叉树,也就是表达式的集合,C#中的Expression类就是表达式类。对于一棵表达式树,其叶子节点都是参数大概常数,非叶子节点都是运算符大概控制符。</p>
<h3>2.1、表达式的创建</h3>
<p>Lambda表达式方法:</p>

Expression<Func<int, int,bool>> fun = (x, y) => x < y

<p>这种方法创建出的表达式根节点类型为ExpressionType.Lambda,Type类型为返回值类型typeof(bool)</p>
<p>组装法(通过 API 创建表达式树):</p>

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

<p>我们先创建了两个参数表达式num和5,然后用LessThan组装在一起,最终的表达式为“num<5”,expr的节点类型为LessThan,Type类型为typeof(bool)</p>
<p>我们先看看表达式树内里的构造</p>
<p>起首Expression<TDelegate>的功能是将强类型Lambda表达式表现为表达式树形式的数据布局,他的父类是LambdaExpression,比力他们代码可知,Lambda表达式的主体,名称和参数全部保存在LambdaExpression内里。</p>
<p>Expression<TDelegate>与LambdaExpression代码截图:</p>
<p><div align="center"></div></p>
<p><div align="center"></div></p>
<p>LambdaExpression内里的Body就是我们的表达式。</p>
<p>C#表达式给我们提供了丰富的表达式类,进入到LambdaExpression类内里</p>
<p><div align="center"></div></p>
<p>方法返回类型以“Expression”末端的,根本上都是一个表达式类。</p>
<p>每个表达式代表的定义和创建方法,可以参照微软官方文档https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.binaryexpression?view=netframework-4.8</p>
<p>下面是平常使用最多的表达式</p>
<p>ConstantExpression:常量表达式</p>
<p>ParameterExpression:参数表达式</p>
<p>UnaryExpression:一元运算符表达式</p>
<p>BinaryExpression:二元运算符表达式</p>
<p>TypeBinaryExpression:is运算符表达式</p>
<p>ConditionalExpression:条件表达式</p>
<p>MemberExpression:访问字段或属性表达式</p>
<p>MethodCallExpression:调用成员函数表达式</p>
<p>Expression<TDelegate>:委托表达式</p>
<h3>2.2、表达式的剖析</h3>
<p>表达式树剖析</p>
<p>通过LambdaExpression类我们可以知道,表达式树包罗:参数,表达式树类型,表达式,返回类型,Lambda表达式的委托以及Lambda表达式名称,如图所示:</p>
<p><div align="center"></div></p>
<p>表达式剖析:</p>
<p>所有的表达式都包罗:左节点【Left】,右节点【Right】,类型【NodeType】,差异的表达式还会有其他属性,这里的左右节点依旧是表达式。</p>
<p>下图是BinaryExpression表达式截图</p>
<p><div align="center"></div></p>
<p>表达式树和表达式内里的类型NodeType是一个罗列,一共有85个类型,有兴趣的朋侪可以去相识下。</p>
<p>常用的类型如下:</p>
<p>ExpressionType.And:C#中雷同于&</p>
<p>ExpressionType.AndAlso:C#中雷同于&&</p>
<p>ExpressionType.Or:C#中雷同于|</p>
<p>ExpressionType.OrElse:C#中雷同于||</p>
<p>ExpressionType.Equal:C#中雷同于==</p>
<p>ExpressionType.NotEqual:C#中雷同于!=</p>
<p>ExpressionType.GreaterThan:C#中雷同于></p>
<p>ExpressionType.GreaterThanOrEqual:C#中雷同于>=</p>
<p>ExpressionType.LessThan:C#中雷同于<</p>
<p>ExpressionType.LessThanOrEqual:C#中雷同于<=</p>
<p>ExpressionType.Add:C#中雷同于+</p>
<p>ExpressionType.AddChecked:C#中雷同于+</p>
<p>ExpressionType.Subtract:C#中雷同于-</p>
<p>ExpressionType.SubtractChecked:C#中雷同于-</p>
<p>ExpressionType.Divide:C#中雷同于/</p>
<p>ExpressionType.Multiply:C#中雷同于*</p>
<p>ExpressionType.MultiplyChecked:C#中雷同于*</p>
<h3>2.3、编译表达式树</h3>
<p>在表达式创建那,我们组合创建了一个Lambda表达式,那么应该怎么使用它呢?在“表达式的剖析”内里,LambdaExpression类和Expression<TDelegate>类都有一个Compile的方法,学名是Lambda表达式的委托,其实就是Lambda表达式编译函数的委托,所以我们只需要调用他,得到的效果就是一个函数方法。</p>
<p>代码修改如下:<br /><br /></p>

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

Console.WriteLine($"Lambda的内容:{lambda1.ToString()}");

//表达式的编译
var func = lambda1.Compile();
Console.WriteLine($"Lambda的运行效果:{func(6)}");


<p>运行效果</p>
<p><div align="center"></div></p>
<h2>三、总结</h2>
<p>这里我们对表达式做了根本的讲解,信赖大家对Lambda表达式有了初步的相识,下面我们将继续讲解对一个表达式树的遍历。</p><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/snailblog/archive/2019/09/15/11521043.html" target="_blank">https://www.cnblogs.com/snailblog/archive/2019/09/15/11521043.html</a>
页: [1]
查看完整版本: C# 表达式树讲解(一)