表达式树练习实践:入门基础

什么是表达式树

来自微软官方文档的定义:

表达式树以树形数据结构表示代码。

它能干什么呢?

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

好不好玩?

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

哪里有应用?

ORM框架、工作流框架等,使用到 Lambda 的代码。。。动态执行代码、动态组装代码等。

创建表达式树

创建表达式树有两种方式:通过 lambda 表达式、通过 API。

创建表达式树的意思是,在此之前已经编写好每个结点,最后使用代码将所有结点组合起来,生成表达式树。

示例(通过API创建表达式树)

```ParameterExpression a = Expression.Parameter(typeof(int), "i");ParameterExpression b = Expression.Parameter(typeof(int), "j");Expression r1 = Expression.Multiply(a, b);ParameterExpression c = Expression.Parameter(typeof(int), "x");ParameterExpression d = Expression.Parameter(typeof(int), "y");Expression r2 = Expression.Multiply(c, d);Expression result = Expression.Add(r1, r2);Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);var com = func.Compile();Console.WriteLine("表达式" + func);Console.WriteLine(com(12, 12, 13, 13));Console.ReadKey();

上面关于表达式树的代码很多,以下这一步叫生成/创建表达式树。

            Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);

以下这句叫执行表达式树

            var com = func.Compile();

其它代码是用于生成表达式树结点/逻辑。

回归正题,创建表达式树的两种方法。

lambda 创建表达式树

上面的表达式树示例,是用于生成

 ( i * j ) + ( x * y )

但是就这么简单的操作,要写这么长,实在不合理。

而通过 lambda ,可以这样写

           Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);

如果使用 lambda 生成表达式树, lambda 只能使用单行语句,不能使用 if、for等语句。

具体关于 Lambda 的表达式树,后面其它文章有说明。

通过 API 创建表达式树

就是这样

Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);

两种方式左边的都是一样的,区别在于等号右边。

Expression< TDelegate >

上面示例的最终结果都是生成

Expression<Func<int, int, int, int, int>> func 

func 是表达式树变量。

我们可以了解以下表达式树具有的方法和属性。

用于生成表达式树结点的,是 Expression 类型。

那么,创建的表达式树 func ,是 Expression<TDelegate>类型。

定义如下

public sealed class Expression<TDelegate> : LambdaExpression

具有方法如下

640?wx_fmt=png

Compile()将表达式树描述的 lambda 表达式编译为可执行代码,并生成表示 lambda 表达式的委托。
Compile(Boolean)将表达式树描述的 Lambda 表达式编译为已解释或已编译的代码,并生成表示该 Lambda 表达式的委托。
Compile(DebugInfoGenerator)将 lambda 编译到方法定义中。(Inherited from LambdaExpression)
Update(Expression, IEnumerable)创建一个与此表达式类似的新表达式,但使用所提供的子级。如果所有子级都相同,则将返回此表达式。
Accept(ExpressionVisitor)调度到此节点类型的特定 Visit 方法。例如,MethodCallExpression调用 VisitMethodCall。

由于 Expression<TDelegate> 继承了 LambdaExpression,所以有很多属性方法也可以用。

640?wx_fmt=png

CanReduce指示可将节点简化为更简单的节点。如果返回 true,则可以调用 Reduce() 以生成简化形式。
Name获取 lambda 表达式的名称。
NodeType返回此 Expression 的节点类型。
Parameters获取 lambda 表达式的参数。
ReturnType获取 lambda 表达式的返回类型。
TailCall获取一个值,该值指示是否将通过尾调用优化来编译 lambda 表达式。
Type获取此 Expression 表示的表达式的静态类型。

好了,以上权当小笔记,备忘,目前先用不上,后面慢慢来使用。

解析/执行表达式树

创建表达式树后,就要执行表达式树。

在此之前,你需要了解 委托 Delegate,Func,Action,以及他们中间的关系。

执行表达式树是这样子的

            Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);var com = func.Compile();var runRasult = com(12, 12, 13, 13);

func 只是一个表达式树,我们把表达式树构建好后,“要将表达式树转为代码”,使用

.Compile() 方法,可以将表达式树生成一个 委托(例如上面的 com)。

为了简洁上面使用了 var,实际上是这样的

            Func<int,int,int,int,int> com = func.Compile();

四个参数,一个返回值。

var runRasult = com(12, 12, 13, 13);

C#里有语法糖,对委托可以这样写

以后后面都是这样写了,能够缩成一行的代码,就没必要写出两行。

在 Vs 里面调试和查看表达式树,可以看这里

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/expression-trees/debugging-expression-trees-in-visual-studio

初学者不必纠结于这些,了解一下本文内容,记一下概要信息即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Servlet与线程安全

Servlet与线程安全 先说结论&#xff0c;Servlet本身是单例的&#xff0c;线程安全的。但是如果引入共享变量&#xff0c;则可能会变得线程不安全。 1. 什么是线程安全 首先说明一下对线程安全的讨论&#xff0c;哪种情况我们可以称作线程安全&#xff1f; 《Java并发编程实…

尝鲜体验 VS Code Python 原生 Jupyter Notebook 支持

9 月 21 日&#xff0c;PyCon China 2019 在上海举办。微软的 VS Code 发布了原生的Juypter Notebook 支持。 虽然要等到月底 Marketplace 里面才会正式更新&#xff0c;但 GitHub 上的 repo 已经包含了相应的 commit&#xff0c;所以还是可以通过手动安装的方式尝鲜。现有 VSC…

Java Web之filter、listener、Interceptor

** 1、Servlet ** Servlet 是服务端的 Java 应用程序&#xff0c;用于处理HTTP请求&#xff0c;做出相应的响应。 当客户端向服务器发出HTTP请求时&#xff0c;首先会由服务器中的 Web 容器&#xff08;如Tomcat&#xff09;对请求进行路由&#xff0c;交给该URL对应的 Servl…

abp vNext微服务框架分析

abp vNext新框架的热度一直都很高&#xff0c;于是最近上手将vNext的微服务Demo做了一番研究。我的体验是&#xff0c;vNext的微服务架构确实比较成熟&#xff0c;但是十分难以上手&#xff0c;对于没有微服务开发经验的.net人员来说几乎是看不懂的&#xff0c;所以研究一番后再…

.NET Conf 2019日程(北京时间)

一年一度的 .NET Conf马上就要开始了,我将日程简易的翻译了一下,并且时间全部转换为北京时间,以方便国内.NETer.第1天 (北京时间9月24日).NET Conf 2019 基调 - Scott Hunter Mads Torgersen James Montemagno Olia Gavrysh Daniel Roth Glenn Condron Bri Achtman欢迎来到 .NE…

Hibernate基础

** 一、什么是Hibernate&#xff1f; **   Hibernate是一个轻量级的ORMapping框架   ORMapping原理&#xff08;Object Relational Mapping&#xff09; ORMapping基本对应规则&#xff1a; 1&#xff1a;类跟表相对应2&#xff1a;类的属性跟表的字段相对应3&#xff1…

进击的.NET 在云原生时代的蜕变

你一定看过这篇文章 《进击的 Java &#xff0c;云原生时代的蜕变》, 本篇文章的灵感来自于这篇文章。北京时间9.24 就将正式发布.NET Core 3.0, 所以写下这篇文章让大家全面认识.NET Core。.NET 生态系统是一个不断变化的生态圈&#xff0c;我相信它正在朝着一个伟大的方向发…

Hibernate懒加载问题的5种解决方案

** 1、Hibernate基础 ** Hibernate基础&#xff0c;传送门 ** 2、什么是Hibernate懒加载 ** 当我们查询一个对象的时候&#xff0c;在默认情况下&#xff0c;返回的只是该对象的代理对象&#xff0c;当用户去使用该对象的属性时&#xff0c;才会向数据库再一次发出查询语…

程序员过关斩将--要想获取我的用户信息,就得按照规矩来

菜菜君&#xff0c;我又来啦又有什么事吗&#xff1f;我按照你上篇文章写的JWT的方式已经把网站认证写完了&#xff0c;而且效果还不错那恭喜你呀&#xff0c;下次面试又多了一项技能不过&#xff0c;现在又有一个问题&#xff0c;我做的系统有一个合作商想要利用我们的用户信息…

E. Surprise me!(莫比乌斯反演 + 虚树 DP)

E. Surprise me! ∑i1n∑j1nϕ(aiaj)d(i,j)设paii∑i1n∑j1nϕ(ij)d(pi,pj)∑i1n∑j1nϕ(i)ϕ(j)ϕ(gcd⁡(i,j))gcd⁡(i,j)d(pi,pj)∑d1ndϕ(d)∑i1nd∑j1ndϕ(id)ϕ(jd)d(pid,pjd)[gcd⁡(i,j)1]∑d1ndϕ(d)∑k1ndμ(k)∑i1nkd∑j1nkdϕ(ikd)ϕ(jkd)d(pikd,pjkd)Tkd∑T1n(∑i1n…

Hibernate 的缓存机制

** 1、Hibernate 应用程序中按照缓存的范围&#xff0c;可以将缓存分为三类 ** &#xff08;1.1&#xff09;事务范围缓存&#xff08;单Session&#xff0c;即一级缓存&#xff09; 事务范围的缓存只能被当前事务访问&#xff0c;每个事务都有各自的缓存。缓存的生命周期依…

.NET分布式大规模计算利器-Orleans(一)

写在前面Orleans是基于Actor模型思想的.NET领域的框架&#xff0c;它提供了一种直接而简单的方法来构建分布式大规模计算应用程序&#xff0c;而无需学习和应用复杂的并发或其他扩展模式。我在2015年下半年开始应用Orleans&#xff0c;当时公司的交易系统采用的架构就是基于Orl…

从单机应用到微服务,用户认证走几步?

用户认证指在用户访问服务的时候确认用户的身份&#xff0c;受限于HTTP无状态的特性&#xff0c;应用开发者需要自行实现用户认证相关功能。通常是用户登录时服务端生成通行证返回给客户端&#xff0c;客户端在接下来的请求中携带通行证&#xff0c;然后服务端通过校验该通行证…

编写优雅代码,从挖掉恶心的if/else 开始

背景长话短说&#xff0c; 作为开发人员经常需要根据条件灵活查询数据库&#xff0c;不管你是用rawsql 还是EFCore&#xff0c; 以下类似伪代码大家都可能遇到&#xff1a;特别是在大数据产品或者物联网产品中&#xff0c;字段甚多&#xff1b;if/else 写到死&#xff0c;一边写…

.NET Conf 2019 大会上发布.NET Core 3.0

北京时间今天凌晨如期在.NET Conf 上发布.NET Core 3.0,Keynotes 由Scott Hunter 主演&#xff0c;主要围绕.NET Core 3.0的新特性和社区展开。多功能性是.Net Core 成为我们的生活一部分的最好解释。如果您是Web开发人员还是想开发桌面或移动应用程序&#xff0c;如果您是游戏…

Spring AOP实现原理

先说结论&#xff1a; Spring AOP采用的是JDK动态代理 CGLIB动态代理模式。当当前类为接口的实现时&#xff0c;采用JDK动态代理&#xff0c;否则用CGLIB、 1、AOP 的存在价值 在传统 OOP 编程里以对象为核心&#xff0c;整个软件系统由系列相互依赖的对象所组成&#xff0c…

微软推出Python免费在线教程视频

开源中国曾报道过最近微软针对 Python 初学者&#xff0c;推出了一套免费的教程视频。这套视频名为 Python for Beginners&#xff0c;该在线教学视频由微软高级项目经理 Christopher Harrison、以及微软 AI Gaming 的商业开发经理 Susan Ibach 共同讲解&#xff0c;在课程中加…

推荐neter常用优秀开源项目系列之一

.net社区有很多优秀的开源项目&#xff0c;我们今天先推荐6个开源项目&#xff1b;1.MassTransitMassTransit 是一个自由、开源、轻量级的消息总线, 用于使用. NET 框架创建分布式应用程序。MassTransit在现有消息传输上提供了一组广泛的功能, 从而使开发人员能够友好地使用基于…

聊聊高并发下库存加减那些事儿——“异步扣减库存”

聊聊高并发下库存加减那些事儿不定期福利发放哦聊聊高并发下库存加减那些事儿背景一般在日常开发中经常会遇到打折促销&#xff0c;秒杀活动&#xff0c;就如拼多多最近的4999抢券买爱疯11促销活动&#xff0c;毕竟谁的钱也不是大风刮来的&#xff0c;有秒杀有促销必定带来大量…

什么是MVC

什么是MVC&#xff1f; MVC全名是Model View Controller&#xff0c;是模型(model)&#xff0d;视图(view)&#xff0d;控制器(controller)的缩写&#xff0c;一种软件设计典范。 用一种业务逻辑、数据、界面显示分离的方法&#xff0c;将业务逻辑聚集到一个部件里面&#xf…