学习表达式树笔记 原

文章地址:  http://www.cnblogs.com/Ninputer/archive/2009/08/28/expression_tree1.html

 //定义一个表达式            
            ConstantExpression exp1 = Expression.Constant(1);
            ConstantExpression exp2 = Expression.Constant(2);
            BinaryExpression exp12 = Expression.Add(exp1, exp2);
            ConstantExpression exp3 = Expression.Constant(3);
            BinaryExpression exp123 = Expression.Add(exp12, exp3);
//需要转为LambdaExpression 后,才能执行
            LambdaExpression lambda = Expression.Lambda(exp123);
            Delegate func = lambda.Compile();
            MessageBox.Show(  func.DynamicInvoke(null).ToString());
//直接定义LambdaExpression 
            ParameterExpression expA=Expression.Parameter(typeof(double),"a");
            MethodCallExpression expCall = Expression.Call(null, typeof(Math).GetMethod("Sin"), expA);
            lambda = Expression.Lambda(expCall, expA);
//这个是表达式字面量,自动从语言层面的表达式转为表达式树。 这个特殊语法只适于Lambda表达式。是一种语法糖!
            Expression<Func<double, double>> exp = a => Math.Sin(a);

表达式树最终是一个内存中树状结构的数据。可以文本化,序列化、转存、传输等等。

  • 运行时分析表达式的逻辑
  • 序列化或者传输表达式
  • 重新编译成可执行的代码

课后习题:

//表达式求值时,验证表达式是否正确 
LambdaExpression lambda = Expression.Lambda(expN, expA);//后面各题的表达式及参数传入此,
Delegate func = lambda.Compile();
MessageBox.Show(func.DynamicInvoke(10).ToString()); //调用时,注意参数要按顺序传入
 
//1、 -a 
ParameterExpression expA = Expression.Parameter(typeof(double), "a");
UnaryExpression expN = Expression.Negate(expA);
//2、a+b*2 
ParameterExpression expA = Expression.Parameter(typeof(double), "a");
ParameterExpression expB = Expression.Parameter(typeof(double), "b");
ConstantExpression exp2=Expression.Constant(2.0);
BinaryExpression expb2 = Expression.Multiply(exp2, expB);
BinaryExpression expab2 = Expression.Add(expA, expb2); 
//3、Math.Sin(x)+Math.Cos(y)
ParameterExpression expx = Expression.Parameter(typeof(double), "x");  
ParameterExpression expy = Expression.Parameter(typeof(double), "y"); 
MethodCallExpression expsin = Expression.Call(null, typeof(Math).GetMethod("Sin"), expx);
MethodCallExpression expcos = Expression.Call(null, typeof(Math).GetMethod("Cos"), expy);
BinaryExpression expAdd = Expression.Add(expsin, expcos);  
//4、new StringBuilder("hello") 
 ConstantExpression exphello = Expression.Constant("hello");
 NewExpression expNew = Expression.New(typeof(StringBuilder).GetConstructor(new Type[] { typeof(string) }), exphello);

之后这4个就不会手写了,根据说明,可以用直接写表达式字面量,然后反编译出表达式来。我用这方法反编译一下:

1、new int[] { a, b, a + b}

        “Expression<Func<int, int, int[]>> exp = (a, b) => new int[] { a, b, a + b };“反编译的,还是自身!原作者说“不过C#编译器有时会使用一些作弊手法,聪明的你应该能找到绕过的手段……” ,我不知道是什么手段

2、a[i – 1] * i

       “Expression<Func<int[], int,int>> exp = (a, i) => a[i-1]*i;”反编译为:

Expression.Lambda<Func<int[], int, int>>(
        Expression.Multiply(
            Expression.ArrayIndex(  //注意这用的方法
                c1 = Expression.Parameter(typeof(int[]), "a"), 
                Expression.Subtract(
                    c2 = Expression.Parameter(typeof(int), "i"), 
                    Expression.Constant(1, typeof(int))
                )
            ), 
            c2), 
        new ParameterExpression[] { c1, c2 }
);

3、a.Length > b | b >= 0

     “Expression<Func<int[], int, bool>> exp = (a, b) => a.Length > b || b > 0;”反编译为:

ParameterExpression c1;
 ParameterExpression c2;
//注意如何获取数组长度。我自己写时,试着: MemberExpression expLen = Expression.Field(expA, "Length")
//结果是不对的。表明length不是一个普通字段 。
Expression<Func<int[], int, bool>> exp = Expression.Lambda<Func<int[], int, bool>>(
     Expression.OrElse(
            Expression.GreaterThan(Expression.ArrayLength(c1 = Expression.Parameter(typeof(int[]), "a")),c2 = Expression.Parameter(typeof(int), "b")),
           Expression.GreaterThan(c2, Expression.Constant(0, typeof(int)))
    ),
    new ParameterExpression[] { c1, c2 }
);

4、new System.Windows.Point() { X = Math.Sin(a), Y = Math.Cos(a) }

    “Expression<Func<double, Point>> exp = (a) => new Point() { X = (int)Math.Sin(a), Y = (int)Math.Cos(a) };”  稍加变形,反编译后还是自身!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏菩提树下的杨过

C#执行XSL转换

xsl 可方便的将一种格式的xml,转换成另一种格式的xml,参考下面的代码: using System; using System.IO; using Sys...

1999
来自专栏landv

从零开始学习C#——HelloWorld(一)

1425
来自专栏GreenLeaves

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

3762
来自专栏二进制文集

JSON Java 解析

要使程序可以运行必须引入JSON-lib包——org.json.jar包。综合来看,这个JAR包比较好用。

1222
来自专栏技术之路

Expression 表达式树学习整理

整理了一下表达式树的一些东西,入门足够了 先从ConstantExpression 开始一步一步的来吧  它表示具有常量值的表达式 我们选建一个控制台应用程序 ...

1858
来自专栏大内老A

由for V.S. for each想到的

一直想写一系列如何提高Performance和Scalability的文章,把我的相关经验和所知道的相关的技巧同大家分享。前一阵在园子里有一篇讨论for eac...

1888
来自专栏码农分享

原型模式(Prototype)

原型模式的结构 原型模式包含以下3个角色: •Prototype(抽象原型类) •ConcretePrototype(具体原型类) •Client(客户...

1103
来自专栏林德熙的博客

win10 uwp unix timestamp 时间戳 转 DateTime

有时候需要把网络的 unix timestamp 转为 C# 的 DateTime ,在 UWP 可以如何转换?

651
来自专栏技术博客

Dynamic 动态类型 和双问号??的使用

1.dynamic关键字用于声明一个动态对象,然后通过该动态对象去调用方法或读写属性。以前我们都是在运行时通过反射,Emit,CodeDom等技术来完成。创建一...

1932
来自专栏Android干货

Java数据解析---JSON

5517

扫码关注云+社区

领取腾讯云代金券