在进入今天的正题之前,先感慨下本人的blog的人气一篇不如一篇。再加上换公司后人身自由受到了比之前大得多得多的限制,实在令本人有些郁闷。不过每次提笔写些东西跟大家分享,总是能让我感到愉悦和欣慰,希望我的文章和理解能帮助到大家。前段时间周星星给我聊天的时候跟我说我写的东西msdn上都能查到,希望我能多写写自己的思考。其实是这样的,就知识查询手册这个层面来说,我相信.net的知识msdn上没有查不到的,我只是努力给大家展现我自己的一个理解和学习的过程,把一些知识以一个特定的逻辑顺序串联起来,希望通过我的一些带有个人色彩的陈述和表达使大家能理解和运用这些知识。

好了,进入正题,上一篇已经说过了,这一篇会写一些轻松的东西,主要来写写表达式树的一些案例和应用,相对而言会比较简单。

我之前已经写过,方法可以做什么表达式树就可以做什么。我们先来看一个例子。

有一个Aircraft的类

public class Aircraft
    {
        public int[] AircraftNumber
        {
            get;
            set;
        }

public string AirlineId
        {
            get;
            set;
        }

public Aircraft()
        { 
        }

public bool Test()
        {
            return true;
        }
    }

首先 我们来看一个函数,这个函数的作用就是判断Aircraft中的AirlineId是否为null,我们先来看看用lambda表达式怎么写

Func<Aircraft, bool> methodEqualNull = item => item.AirlineId == null;

好,现在问题来了。如果我们需要在运行时来构建这个逻辑怎么办,具体一点,比如我们需要把这个AirlineId当成参数传进来,就是运行时判断哪个属性是否为null怎么办,然后甚至null也是运行时动态传进来的怎么办,即,我们需要运行时判断某个属性是否等于某个具体常量,怎么办。

这个时候我们就可以用表达式树了。

ParameterExpression aircraftParameter = Expression.Parameter(typeof(Aircraft), "aircraftTestString");
 MemberExpression memberAirlineIdExpression = Expression.Property(aircraftParameter, "AirlineId");
 ConstantExpression nullConstant = Expression.Constant(null);
  Expression<Func<Aircraft, bool>> equalNull = Expression.Lambda<Func<Aircraft, bool>>
                                                                         (Expression.Equal  (memberAirlineIdExp ression, nullConstant),
                                                                          new ParameterExpression[] { aircraftParameter }
                                                                          );

我们先来普及下表达式树中几个常用的类:

ParameterExpression:参数表达式,用于表示表达式树中需要用到的参数

MemberExpression:成员表达式,用于表示某个ParameterExpression中的某个成员

好,知道了这2个概念,我们就来分析下这2句话:

ParameterExpression aircraftParameter = Expression.Parameter(typeof(Aircraft), "aircraftTestString");

这一句表示表达式树中有一个参数,它的类型是Aircraft,
 MemberExpression memberAirlineIdExpression = Expression.Property(aircraftParameter, "AirlineId");

这一句表示有一个memberAirlineIdExpression ,这个变量用来表示Aircraft这个类型中的AirlineId这个属性

ConstantExpression:这个简单,就是常量表达式

Expression.Lambda<Func<Aircraft, bool>>
                                                                         (Expression.Equal(memberAirlineIdExpression, nullConstant),
                                                                          new ParameterExpression[] { aircraftParameter }
                                                                          );

这句代码很重要,我们具体分析下,首先它表示构建一个参数为Aircraft,返回类型为bool的表达式树,

new ParameterExpression[] { aircraftParameter },这句话表示这个表达式树的参数为aircraftParameter ,

Expression.Equal(memberAirlineIdExpression, nullConstant)这句话表示这个表达式的逻辑是判断memberAirlineIdExpression和nullConstant是否相等。

好了,有了上面的例子,我们再来看一个类似的表达式树,它要构建出item => item.AirlineId == string.Empty这个逻辑

ConstantExpression emptyConstant = Expression.Constant(string.Empty);
Expression<Func<Aircraft, bool>> equalEmpty = Expression.Lambda<Func<Aircraft, bool>>
                                                                          (
                                                                            Expression.Equal(memberAirlineIdExpression, emptyConstant),
                                                                            new ParameterExpression[] { aircraftParameter }
                                                                          );
            

好了,通过上面两个例子,我们可以看出,如果运用表达式树,ParameterExpression,MemberExpression,都可以在运行时当成参数传入,也都可以在运行时动态构建,甚至如果大家自己尝试,大家可以发现,Expression.Equal这个很核心的逻辑,我们都可以通过传入一个字符串,然后调用Expression.Call方法来构建,但我在此不推荐这么做,因为字符串没有编译时的检查,很不完全,就算是一个没有对应具体方法的字符串也可以被传入。

然后,已经构建好的表达式树也可以被其他的表达式树调用,我们再来看个例子

Expression<Func<Aircraft, bool>> expressionString = Expression.Lambda<Func<Aircraft, bool>>
                                                                           (
                                                                             Expression.Or(equalNull.Body, equalEmpty.Body),
                                                                             new ParameterExpression[] { aircraftParameter }
                                                                           );

这段代码就是运用之前的2个表达式树,构建了一个string.IsNullOrEmpty的逻辑。

顺带说一下,Body和Parameter是表达式树中2个很核心的概念,我会在下一篇博文中具体来说。

好,我曾经说过,方法可以做的事情表达式树都可以做,因为实际上方法可以按照表达式树的形式来进行保存。

大家可以参考下这篇文章http://rednaxelafx.javaeye.com/blog/247270

我作一些摘抄

算术表达式部分

static void Add( ) {

// Expression<Func<int, int, int>> add = ( x, y ) => x + y;

ParameterExpression x = Expression.Parameter( typeof( int ), "x" );

ParameterExpression y = Expression.Parameter( typeof( int ), "y" );

Expression<Func<int, int, int>> add = Expression.Lambda<Func<int, int, int>>(

Expression.Add(

x, // left

y // right

),

new ParameterExpression[ ] { x, y }

);

}

按位运算表达式

// "<<" operator

static void LeftShift( ) {

// Expression<Func<int, int, int>> lshift = ( x, y ) => x << y;

ParameterExpression x = Expression.Parameter( typeof( int ), "x" );

ParameterExpression y = Expression.Parameter( typeof( int ), "y" );

Expression<Func<int, int, int>> lshift = Expression.Lambda<Func<int, int, int>>(

Expression.LeftShift(

x, // left

y // right

),

new ParameterExpression[ ] { x, y }

);

}

条件表达式

// "? :" operator

static void Condition( ) {

// Expression<Func<bool, int, int, int>> cond = ( c, x, y ) => c ? x : y;

ParameterExpression c = Expression.Parameter( typeof( bool ), "c" );

ParameterExpression x = Expression.Parameter( typeof( int ), "x" );

ParameterExpression y = Expression.Parameter( typeof( int ), "y" );

Expression<Func<bool, int, int, int>> cond = Expression.Lambda<Func<bool, int, int, int>>(

Expression.Condition(

c, // test

x, // if true

y // if false

),

new ParameterExpression[ ] { c, x, y }

);

}

等于大于小于等比较大小的部分

static void GreaterThan( ) {

// Expression<Func<int, int, bool>> gt = ( x, y ) => x > y;

ParameterExpression x = Expression.Parameter( typeof( int ), "x" );

ParameterExpression y = Expression.Parameter( typeof( int ), "y" );

Expression<Func<int, int, bool>> gt = Expression.Lambda<Func<int, int, bool>>(

Expression.GreaterThan(

x, // left

y // right

),

new ParameterExpression[ ] { x, y }

);

}

关系表达式

static void AndAlso( ) {

// Note that And() is for bitwise and, and AndAlso() is for logical and.

// Note also that the shortcut semantics is implemented with AndAlso().

// Expression<Func<bool, bool, bool>> and = ( x, y ) => x && y;

ParameterExpression x = Expression.Parameter( typeof( bool ), "x" );

ParameterExpression y = Expression.Parameter( typeof( bool ), "y" );

Expression<Func<bool, bool, bool>> and = Expression.Lambda<Func<bool, bool, bool>>(

Expression.AndAlso(

x, // left

y // right

),

new ParameterExpression[ ] { x, y }

);

}

类型转换表达式

// C-style conversion

static void Convert( ) {

// Expression<Func<int, short>> conv = x => ( short ) x;

ParameterExpression x = Expression.Parameter( typeof( int ), "x" );

Expression<Func<int, short>> conv = Expression.Lambda<Func<int, short>>(

Expression.Convert(

x,              // expression

typeof( short ) // type

),

new ParameterExpression[ ] { x }

);

}

成员表达式

// C-style conversion

static void Convert( ) {

// Expression<Func<int, short>> conv = x => ( short ) x;

ParameterExpression x = Expression.Parameter( typeof( int ), "x" );

Expression<Func<int, short>> conv = Expression.Lambda<Func<int, short>>(

Expression.Convert(

x,              // expression

typeof( short ) // type

),

new ParameterExpression[ ] { x }

);

}

数组表达式

static void ArrayIndex( ) {

// Expression<Func<int[ ], int, int>> aryIdx = ( a, i ) => a[ i ];

ParameterExpression a = Expression.Parameter( typeof( int[ ] ), "a" );

ParameterExpression i = Expression.Parameter( typeof( int ), "i" );

Expression<Func<int[ ], int, int>> aryIdx = Expression.Lambda<Func<int[ ], int, int>>(

Expression.ArrayIndex(

a, // array

i // index

),

new ParameterExpression[ ] { a, i }

);

}

方法/委托调用表达式

// Calling a static method

static void Call( ) {

// Note that to call a static method, use Expression.Call(),

// and set "instance" to null

// Expression<Func<string, int>> scall = s => int.Parse( s );

ParameterExpression s = Expression.Parameter( typeof( string ), "s" );

Expression<Func<string, int>> scall = Expression.Lambda<Func<string, int>>(

Expression.Call(

null,                      // instance

typeof( int ).GetMethod(   // method

"Parse", new Type[ ] { typeof( string ) } ),

new Expression[ ] { s }    // arguments

),

new ParameterExpression[ ] { s }

);

}

https://www.cnblogs.com/FlyEdward/archive/2010/04/15/Linq_ExpressionTree5.html

转载于:https://www.cnblogs.com/sjqq/p/8567134.html

Linq系列(5)——表达式树之案例应用相关推荐

  1. C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)

    Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string ...

  2. C#编程(六十六)----------表达式树总结

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

  3. 关于Expression表达式树的拼接

    关于Expression表达式树的拼接 最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有i ...

  4. 表达式树(EXPRESSION TREE)

    表达式树是不可执行的代码,它只是用于表示一种树状的数据结构,树上的每一个节点都表示为某种表达式类型,大概有25种表达式类型,它们都派生自Expression类.创建表达式树具体有两个优势: 1.对表达 ...

  5. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截...

    程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少.数据 ...

  6. 只要十步,你就可以应用表达式树来优化动态调用

    表达式树是 .net 中一系列非常好用的类型.在一些场景中使用表达式树可以获得更好的性能和更佳的扩展性.本篇我们将通过构建一个 "模型验证器" 来理解和应用表达式树在构建动态调用方 ...

  7. 【C#复习总结】细说表达式树

    1 前言 系类1:细说委托 系类2:细说匿名方法 系列3:细说Lambda表达式 系列4:细说泛型委托 系列5:细说表达式树 系列6:细说事件 涛声依旧,再续前言,接着用大佬的文章作为开头. 表达式树 ...

  8. 不能不说的C#特性-表达式树

    最近发生了很多很多事情,频繁的搬家.工作上的事情也挺多的,所以博客更新的非常缓慢. 已经有很多很多人聊过这个话题,今天我在这里重复也不会探讨出什么新东西,只是把自己的理解描述出来,更是为了整个系列文章 ...

  9. Lambda表达式表达式树

    在C#3.0中,继匿名方法之后出现了Lambda 表达式,使表达更为简洁.快捷.Lambda 表达式使用Lambda 运算符 "=>"来定义,语法如下: (参数列表) =&g ...

  10. SQL、Linq和Lambda表达式 的关系

    首先说说这三者完全是三种不同的东西,SQL是结构化查询语言(Structured Query Language)简称,这大家再熟悉不过了,下面主要介绍LINQ和Lambda表达式的基本概念以及同一查询 ...

最新文章

  1. K-BERT | 基于知识图谱的语言表示模型
  2. centos添加新硬盘
  3. Android Studio的使用(三)--包不分级、修改包名
  4. oracle的quit命令,Oracle的启动和关闭
  5. 用python画猫咪怎么画-如何用Python实现可视化地图
  6. 机器学习知识点(十六)集成学习AdaBoost算法Java实现
  7. python—多线程之数据混乱问题
  8. 我如何预测10场英超联赛的确切结果
  9. 中国酒精炉行业市场供需与战略研究报告
  10. java点击按钮弹出警告_GUI求教~~~我想点击按钮确定后,弹出一个提示框输入有误!,,…...
  11. opengl 旋转矩阵和纹理坐标相乘_OpenGL-Rotating Points
  12. linux操作系统日志查看,linux 如何查看系统日志
  13. 从零开始搭建一个K8S的环境
  14. 【深度学习框架】-Caffe(入门级学习一:简单介绍)
  15. 使用hexo基于cactus仙人掌主题最全美化客制教程
  16. oracle10g笔记1
  17. Hive on Hbase
  18. 向人工盘点库存和物品说再见
  19. AgentWeb , 一个简洁易用的 Android Web 库
  20. 河南单招计算机专业专科学校排名2015,河南省单招大专学校排名榜 哪个学校好...

热门文章

  1. 全面解析Oracle等待事件的分类、发现及优化
  2. Netty框架中的@Skip使用说明
  3. Android程序开发:简单电话拨号器
  4. zw版【转发·台湾nvp系列Delphi例程】.NET调用HALCON COM控件内存释放模式
  5. 本地源制作docker镜像
  6. plsql为字段添加自增主键
  7. 第六章 jQuery中的Ajax应用
  8. php echo substr('hello',1,-2);-2是什么意思 为什么结果是 el
  9. windows 2003常用命令(推荐)
  10. Qt5学习笔记之bin文件合成工具四:完善功能打包程序