在Sieve组件中使用了很多关于表达式树的知识,但在我们日常的工作中写表达式树的机会是非常少的,至少在我的编程生涯中没怎么写过表达式树(可能也就是3,4次)。所以,为了能够看懂Sieve里面的源代码,我决定还是再重新回顾一下表达式树这个知识点。

IEnumerable和IQueryable

表达式树提供了一个将可执行代码转换成数据的方法.如果你要在执行代码之前修改或转换此代码,那么它是很有用的.有其是当你要将C#代码—-如LINQ查询表达式转换成其他代码在另一个程序—-如SQL数据库里操作它.

说到表达式树就不能不提到两个接口,一个接口是IEnumerable和它的泛型等价接口IEnumerable<out T>(后者继承自前者),还有一个就是IQueryable和它的泛型等价接口IQueryable<out T>(后者从前者继承)。

来看一下两个接口的定义:

    //// 摘要://     Exposes the enumerator, which supports a simple iteration over a collection of//     a specified type.//// 类型参数://   T://     The type of objects to enumerate.public interface IEnumerable<out T> : IEnumerable{//// 摘要://     Returns an enumerator that iterates through the collection.//// 返回结果://     An enumerator that can be used to iterate through the collection.IEnumerator<T> GetEnumerator();}    //    // 摘要:    //     Exposes an enumerator, which supports a simple iteration over a non-generic collection.    public interface IEnumerable    {        //        // 摘要:        //     Returns an enumerator that iterates through a collection.        //        // 返回结果:        //     An System.Collections.IEnumerator object that can be used to iterate through        //     the collection.        IEnumerator GetEnumerator();    }

 //// 摘要://     Provides functionality to evaluate queries against a specific data source wherein//     the type of the data is not specified.public interface IQueryable : IEnumerable{//// 摘要://     Gets the type of the element(s) that are returned when the expression tree associated//     with this instance of System.Linq.IQueryable is executed.//// 返回结果://     A System.Type that represents the type of the element(s) that are returned when//     the expression tree associated with this object is executed.Type ElementType { get; }//// 摘要://     Gets the expression tree that is associated with the instance of System.Linq.IQueryable.//// 返回结果://     The System.Linq.Expressions.Expression that is associated with this instance//     of System.Linq.IQueryable.Expression Expression { get; }//// 摘要://     Gets the query provider that is associated with this data source.//// 返回结果://     The System.Linq.IQueryProvider that is associated with this data source.IQueryProvider Provider { get; }}//// 摘要://     Provides functionality to evaluate queries against a specific data source wherein//     the type of the data is known.//// 类型参数://   T://     The type of the data in the data source.public interface IQueryable<out T> : IEnumerable<T>, IEnumerable, IQueryable{}

在IQueryable接口中有一个Expression类型的属性,这个属性表明IQueryable是有一个表达式树来和它关联的。

撤这么多就是为了阐述一个知识,IEnumerable用于linq to object,在内存中操作数据时,我们使用的是IEnumerable接口,当Linq查询需要从远程数据库比如SqlServer服务器上面查找数据时,这时得用IQueryable接口,IQueryable接口所代表的查询会通过其Expression属性翻译成目标平台的SQL语句来执行查询并最终返回数据。从这个层面上来说,Expression是作为一个中间层来被不同的LINQ to SQL翻译成目标平台的语言(文本,sql)。扯的有点儿远,继续复习Expression的API。

表达式树

System.Linq.Expressions命名空间中包含了代表各种表达式的各个类。他们都继承自Expression。Expression主要包含了各种工厂方法,这些方法用于创建其他表达式的实例。然而,Expression表达式也包含了两个属性

  • Type属性代表表达式求值后的.NET类型,可把它视作一个返回类型。例如:
 Expression first = Expression.Parameter(typeof(string), "x");MemberExpression propertyEx = Expression.MakeMemberAccess(first, typeof(string).GetProperty("Length"));Console.WriteLine(propertyEx.Type);//返回int

  • NodeType属性返回的是所代表的表达式种类。它是ExpressionType的枚举成员。包括LessThan、Multiply和Invoke以及上面这个例子会返回一个MemberAccess类型的Type。

Expression有许多派生类, 其中一些可能有多个不同的节点类型。 例如, BinaryExpression就代表了具有两个操作数的任意操作: 算术、逻辑、比较、数组索引,等等。 这正是 NodeType属性重要的地方,因为它能区分由相同的 类表示的不同种类的表达式。

下面演示一个非常简单的表达式树的创建过程:

ConstantExpression first = Expression.Constant(2);
ConstantExpression second = Expression.Constant(3);
BinaryExpression body = Expression.Add(first, second);
Console.WriteLine(body.Type);//int
Console.WriteLine(body.NodeType);//Add

我们想要表达两个常量相加的一个表达式树,过程就是首先创建这两个常量表达式,然后根据这两个表达式创建一个相加表达式。逻辑结构如下图所示:

将表达式树编译成委托

LambdaExpression是Expression的子类之一,而Expression<TDelegate>又是LambdaExpression的子类,他们的继承结构如下:

Expression和Expression<TDelegate>的区别就在于,泛型的Expression是以静态类型的方式(编译期就已经明确了表达式的类型)标识了它是什么类型的表达式,也就是说它确定了返回类型和参数。我们可以用Expression.Lambda来返回一个泛型Expression。那Expression<TDelegate>的意义何在呢?首先,LambdaExpression有一个Compile方法能够创建恰当类型的委托。Expression<TDelegate>也有一个同名的方法,但它静态类型化后返回的是TDelegate类型的委托。下面的代码演示了这个特性:

ConstantExpression first = Expression.Constant(2);
ConstantExpression second = Expression.Constant(3);
BinaryExpression body = Expression.Add(first, second);
Func<int> func = Expression.Lambda<Func<int>>(body).Compile();
Console.WriteLine(func());//5

为了要打印一个5耗费了大量的时间但这并不是表达式树的本意,我们在程序中编辑了一些逻辑块,然后编译器将这些逻辑块变成真正可以执行的东西,此外,Expression<TDelegate>也有省事儿的方法,-----它可以直接由lambda表达式来显示或者隐式的转换。比如:

Expression<Func<string,int>> expression=it=>it.Length;

Lambda表达式转换成表达式树

Lambda表达式可以转换成委托,同样,他也可以转换成Expression<TDelegate>。

 Expression<Func<int>> expression = () => 5;Func<int> func = expression.Compile();Console.WriteLine(func());

幸亏有了这样的转换,要不我们使用表达式会累死!!!但是他也有一些限制,只能转换单一的表达式。总之如果你的lambda在编译的过程中报错了你就会知道这些限制,这里就不一一列出了。下面演示一个更复杂的:

Expression<Func<string, string, bool>> expression = (x, y) => x.StartsWith(y);
var compiled = expression.Compile();
Console.WriteLine(compiled("pangjainxin", "pang"));

如果没有lambda表达式的隐式转换,那么我们得书写下面的代码来达到这个目的:

            //①首先构造方法调用的各个部件MethodInfo startWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });var target = Expression.Parameter(typeof(string), "x");var methodArg = Expression.Parameter(typeof(string), "y");Expression[] methodArgs = new[] { methodArg };//②然后从以上部件创建CallExpressionExpression call = Expression.Call(target, startWith, methodArgs);//③然后从CallExpression转换成lambda表达式var lambdaParameters = new[] { target, methodArg };var lambda = Expression.Lambda<Func<string, string, bool>>(call, lambdaParameters);var compiled = lambda.Compile();Console.WriteLine(compiled("pangjainxin", "pang"));//trueConsole.WriteLine(compiled("pangjianxin", "angjianxin"));//false

看起来要比隐式的lambda转换麻烦多了,下图展示了这一过程:

转载于:https://www.cnblogs.com/pangjianxin/p/10791710.html

asp.net core 排序过滤分页组件:sieve(2)表达式树的复习相关推荐

  1. ASP.NET Core MVC – Tag Helper 组件

    ASP.NET Core Tag Helpers系列目录,这是第五篇,共五篇: ASP.NET Core MVC – Tag Helpers 介绍 ASP.NET Core MVC – Caching ...

  2. asp.net core MVC 过滤器之ActionFilter过滤器(二)

    简介 Action过滤器将在controller的Action执行之前和之后执行相应的方法. 实现一个自定义Action过滤器 自定义一个全局异常过滤器需要实现IActionFilter接口 publ ...

  3. ASP.NET Core Blazor Webassembly 之 组件

    关于组件 现在前端几大轮子全面组件化.组件让我们可以对常用的功能进行封装,以便复用.组件这东西对于搞.NET的同学其实并不陌生,以前ASP.NET WebForm的用户控件其实也是一种组件.它封装ht ...

  4. Asp.Net Core中利用Seq组件展示结构化日志功能

    在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...

  5. Creating a Pager Control for ASP.NET以及Dino Esposito 分页组件的一个 Bug

    我在使用MSDN 上 Dino Esposito 的分页组件对DataGrid进行操作的时候,发现在 PagingMode="NonCached" 时候,最后一页的时候,会报错误: ...

  6. ASP.NET Core MVC 之视图组件(View Component)

    1.视图组件介绍 视图组件是 ASP.NET Core MVC 的新特性,类似于局部视图,但它更强大.视图组件不使用模型绑定,并且仅依赖于调用它时所提供的数据. 视图组件特点: 呈块状,而不是整个响应 ...

  7. asp.net core MVC 过滤器之ExceptionFilter过滤器(一)

    简介 异常过滤器,顾名思义,就是当程序发生异常时所使用的过滤器.用于在系统出现未捕获异常时的处理. 实现一个自定义异常过滤器 自定义一个异常过滤器需要实现IExceptionFilter接口 publ ...

  8. 这本694页的程序员砖头书让你精通ASP.NET Core MVC

    ASP.NET Core MVC是一个来自微软的Web应用程序开发框架,它结合了模型-视图-控制器(MVC)体系结构的有效性和整洁性.敏捷开发的想法和技术,以及.NET平台的最佳部分. 1.1 ASP ...

  9. ASP.NET Core 中间件(Middleware)详解

    ASP.NET Core 中间件(Middleware)详解 原文:ASP.NET Core 中间件(Middleware)详解 本文为官方文档译文,官方文档现已非机器翻译 https://docs. ...

最新文章

  1. go 方法接受者 是指针类型和非指针类型的 区别
  2. 纽大副教授炮轰NeurIPS、AAAI等顶会:无聊、就不该继续存在
  3. 关于自定义控件设计时如何把属性写入aspx中的研究(上)
  4. 一文搞懂 Java 泛型,非常详细!
  5. linux mysql 修改root密码_MySQL忘了root密码,如何修改?
  6. S32K MCAL02-FlexCAN 时钟模块【理论部分】
  7. OMRON_PLC_CP1H_HostLink通讯协议解析
  8. 利用matlab符号变量进行矩阵乘法公式推导
  9. 本地软件仓库配置及NFS安装
  10. 串口服务器调试助手使用教程,串口服务器如何配置及串口调试6大技巧
  11. 不忘初心Windows11精简版
  12. 新兴研究将如何更好地应对社会挑战?我们等你来共同探讨!
  13. 搭建直播平台过程中的全能“辅助”——流媒体服务器
  14. 力扣 179. 最大数
  15. 3章等价类划分法-城市号码
  16. 重庆师范大学计算机技术排名,2017年重庆师范大学专业排名
  17. 真正的帅哥没人说帅_男生长得帅的标准五官 教你判断谁才是真正的帅哥
  18. bug_ renren-fast注册到 nacos上
  19. html中一条单线这么设置,html单线表格制作方法
  20. for循环语法以及range函数

热门文章

  1. std::move 左值右值 左值引用右值引用
  2. 博微三维技术篇【四】——大规模、高精度三维场景渲染
  3. 设置charles代理后电脑浏览器与手机模拟器都无法连网
  4. 英格索兰整体解决方案助力汽车制造行业不断升级
  5. 面具busybox模块_【Linux技术】BusyBox详解
  6. M302A-JL、M302A-MQ、M302A-ZN_S905L2_通刷-当贝桌面线刷固件包
  7. live2d_为你的网站加上live2d的动态小挂件,博君一晒
  8. 重装系统操作步骤、批处理及注意事项
  9. 一个“网络混子”做网站近一年来的一点随感
  10. 使用IText5+Freemarker生成PDF(模板可以使用CCS3分页效果)