表达式树可使用Expressions类的静态工厂方法来创建。这种用API的方式创建给予我们在编程极大的灵活性,MSDN上关于表达式的例子也不少,但在使用过程中还是会遇到许多麻烦,对有的表达式类,介绍得不是太清楚。这里把一些常见的表达示类的使用整理了下。
 
BinaryExpression类: 是表示包含二元运算符的表达式。

  比如构建形如 (100+88)是个典型的 a+b 式的二元计算,表达式代码如下

BinaryExpression binaryexp = Expression.MakeBinary
(ExpressionType.Add, Expression.Constant(), Expression.Constant());
Console.WriteLine(Expression.Lambda(binaryexp).Compile().DynamicInvoke());

输出: 188

MakeBinary是在Expressions中定义的一个静态工厂方法(根据ExpressionType来选择调用),最终调用的是Expression.Add 静态方法
所以是与下面操作等效的

BinaryExpression binaryexp = Expression.Add(Expression.Constant(), Expression.Constant());

a+b的值类型的操作比较简单,但如果是 "100"+"88" 呢,改下上面的操作

BinaryExpression binaryexp = Expression.Add(Expression.Constant(""), Expression.Constant(""));
Console.WriteLine(Expression.Lambda(binaryexp).Compile().DynamicInvoke());

但这时会报错 “没有为类型“System.String”和“System.String”定义二进制运算符 Add”,这是怎么回事,在我们代码时如果写 string s= "100"+"88";是没错的啊。实际上字串的 +  在生成IL代码时,会转换成 string 的 Concat 扩展方法来操作。因此要实现如  "100"+"88" 还是稍显麻烦

第一步:获取Concat方法的MethodInfo

MethodInfo mif = typeof(string).GetMethods().First(m => m.Name == "Concat" && m.GetParameters().Length ==2);
    因为Concat的参数是可变的方法参数,获取MethodInfo,一定要加上m.GetParameters().Length=实际调用时的参数个数据,不然会出现参数不匹配错误。

第二步:使用MakeBinary的另一个重载方法

    BinaryExpression binaryexp = Expression.Add(Expression.Constant(""), Expression.Constant(""), mif);
Console.WriteLine(Expression.Lambda(binaryexp).Compile().DynamicInvoke());

输出: 10088

回头再看 Expression.Add 的实现

 if (!(method == (MethodInfo) null))
return Expression.GetMethodBasedBinaryOperator(ExpressionType.Add, left, right, method, true);
if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type))
return (BinaryExpression) new SimpleBinaryExpression(ExpressionType.Add, left, right, left.Type);
else
return Expression.GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Add, "op_Addition", left, right, true);

从中看出,当参数年method为null 时,实际上要检查 TypeUtils.IsArithmetic(left.Type),而IsArithmetic的定义为

  internal static bool IsArithmetic(Type type)
{
type = TypeUtils.GetNonNullableType(type);
if (!type.IsEnum)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
return true;
}
}
return false;
}

所以Expression.Add(Expression.Constant("100"), Expression.Constant("88"))在不给定操作方法时,会报错。当指定操作方法时,表达式虽然用tostring 是  "100"+"88" ,但调用的操作方法是 string.Concat。就象用方法表达式一样

MethodCallExpression methExp = Expression.Call(mif, Expression.Constant("100"), Expression.Constant("88"));

因此在调用  Expression.Lambda(binaryexp).Compile().DynamicInvoke();和 Expression.Lambda(methExp).Compile().DynamicInvoke();的结果是一样的

另外从 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) 前部分看,Add方法是要求类型完全相同,在看上去可行的表达式 Expression.Add(Expression.Constant(100), Expression.Constant(88.0)) (后面是Double类型 ),也会报错。而就当改为
 Expression.Add(Expression.Constant((Double)100), Expression.Constant(88.0)) 或 Expression.Add(Expression.Constant(100.0), Expression.Constant(88.0)) 。

表达式:使用API创建表达式树(1)的更多相关文章

  1. 表达式:使用API创建表达式树(3)

    一.DebugInfoExpression:发出或清除调试信息的序列点. 这允许调试器在调试时突出显示正确的源代码. static void Main(string[] args) { var asm ...

  2. 表达式:使用API创建表达式树(2)

    一.BlockExpression类:表式一个包含可在其中定义变量的表达式序列的块.是一组表达式,类似于多个委托的 += 后的效果,其返回表达式是最后一个表达式决定.以下是BlockExpressio ...

  3. 表达式:使用API创建表达式树(6)

    一.ConstantExpression:表示具有常量值的表达式.因为表达式应用过程中,参数据多是 Expressions 类型,算是对常量值的一种包装吧. ConstantExpression使用比 ...

  4. 表达式:使用API创建表达式树(5)

    一.ConditionalExpression:表达式 生成如 IIF((a == b), "a和b相等", "a与b不相等") 式子. 使用: Paramet ...

  5. 表达式:使用API创建表达式树(4)DynamicExpression

    DynamicExpression:表示动态操作.这个网上可见的资料少得可怜,但想到MVC和第三方的动态语言能在NET运行.好奇的倒腾了下 先声明两个类(有相同的方法和字段,但不是继承于同一接口的类) ...

  6. EF4.0、4.3创建表达式树状动态查询总结

    ---------------------------------------------快速适用 效果: where name like '%王%' and Age>=35 or Age< ...

  7. 【C#表达式树 五】工厂模式创建表达式树节点

    常量 1.值常量  (p)=>100+88+p ParameterExpression par = Expression.Parameter(typeof(int), "p" ...

  8. [C# Expression] 之动态创建表达式

    上一篇中说到了 Expression 的一些概念性东西,其实也是为了这一篇做知识准备.为了实现 EFCore 的多条件.连表查询,简化查询代码编写,也就有了这篇文章.   在一些管理后台中,对数据进行 ...

  9. NX二次开发-NX11创建表达式组NXOpen::ExpressionGroup

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_part.h> #include < ...

随机推荐

  1. 新站如何做SEO及注意事项

    最近公司做了新网站,完成后运营优化的工作就落在我身上了,由于之前也没有.就去网上百度了一下,上了各种论坛查阅大牛的博客.自己也总结了一些要点,在这里和大家分享一下.新网站大家可以点击查看牛羊养殖在线. ...

  2. EasyPR--开发详解

    我正在做一个开源的中文车牌识别系统,Git地址为:https://github.com/liuruoze/EasyPR. 我给它取的名字为EasyPR,也就是Easy to do Plate Reco ...

  3. [HDOJ 5155] Harry And Magic Box

    题目链接:HDOJ - 5155 题目大意 有一个 n * m 的棋盘,已知每行每列都至少有一个棋子,求可能有多少种不同的棋子分布情况.答案对一个大素数取模. 题目分析 算法1: 使用容斥原理与递推. ...

  4. JS----Issue

    HTTP Post Form Data:以明文提交的,因此要加密 http://pajhome.org.uk/crypt/md5/index.html

  5. 【spring-boot】spring aop 面向切面编程初接触--切点表达式

    众所周知,spring最核心的两个功能是aop和ioc,即面向切面,控制反转.这里我们探讨一下如何使用spring aop. 1.何为aop aop全称Aspect Oriented Programm ...

  6. Yii widget使用

    关于widgets,他们在yii中的关系如下 system.web.widgets 系统自带最基本的widget zii.widgets 是基本扩展 zii.widgets.grid 是基本扩展的重要 ...

  7. Hadoop环境搭建-入门伪分布式配置(Mac OS,0.21.0,Eclipse 3.6)

    http://www.linuxidc.com/Linux/2012-10/71900p2.htm http://andy-ghg.iteye.com/blog/1165453 为Mac的MyEcli ...

  8. css分割线 文字居中的7种实现方式

    最近开始研究前端,会不定期更新一些小块代码,写下自己的学习笔记,也希望能和大家一起进步! 1.单个标签实现分隔线: <html> <head lang="en"& ...

  9. java+ mysql 给所有的表添加假数据

    需求:别的项目, 代码扣过来了, 数据库也拿过来了, 但是数据库全是空表, 一共700 张表,需求是给表添加假数据,让它能运行起来. 一下是代码实现: 1.数据库连接: public static C ...

  10. XP的定时关机命令?

    Windows XP的关机是由Shutdown.exe程序来控制的,位于Windows/System32文件夹中.如 果想让Windows 2000也实现相同的效果,能够把Shutdown.exe拷贝 ...