本文共 2405 字,大约阅读时间需要 8 分钟。
表达式树听起来就是很神秘,很高端的东西,一直只听闻其酷炫,而未见其真容,今天了解了一下,有一些感悟,记录如下。
1.什么是表达式树
表达式树是将我们原来可以直接由代码编写的逻辑以表达式的方式存储在树状的结构里,从而可以在运行时去解析这个树,然后执行,实现动态的编辑和执行代码。
2.表达式树案例
1)最简单的表达式树
Expression这就是最简单的一个表达式树,仅仅包含一个lamda表达式。上面我们提到表达式树是多个代码逻辑的组合,只不过在运行时编译。那我们如何使用这个表达式树呢?> exp = x => x + 1;
Console.WriteLine(exp.Compile().DynamicInvoke(4));我们看看上面这句话,Compile方法意思是编译这个表达式树,然后调用DynamicInvoke方法去调用,这个和我们上面所说的动态编译执行是一致的。
这里Compile方法返回的是一个Fun<int,int>委托,从表达式树的定义上我们可以看到,表达式树只是在Fun<int,int>外面包了一层Expression,这样我们就能够更好地理解表达式树的实质含义了。
Dynamic方法的作用自然是调用逻辑了,这里需要注意的是,在API中提到的late-bound,这个意思也就是说,如果这个委托绑定过多个方法,那么DynamicInvoke调用的将是最后一次绑定的那个方法。
表达式树有三个重要的要素,那就是Body,ReturnType 和 Parameters
Expression2)稍微复杂的表达式树> exp = x => x + 1;var lambdaExpr = exp as LambdaExpression; Console.WriteLine(lambdaExpr.Body); Console.WriteLine(lambdaExpr.ReturnType.ToString()); foreach (var parameter in lambdaExpr.Parameters){ Console.WriteLine("Name:{0}, Type:{1}, ", parameter.Name, parameter.Type.ToString());}
LoopExpression loopExpression = Expression.Loop( Expression.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), Expression.Constant("Expression")));BlockExpression block = Expression.Block(loopExpression);Expression上面的语句创建了一个循环(loop)表达式,Expression.Call是循环的主体,调用Console.WriteLine方法,参数是Expression,Expression.Constant表示参数是一个固定值。lambdaExpression = Expression.Lambda (block);lambdaExpression.Compile().Invoke();
BlockExpression是一个语句块对象,最后通过Expression.Lambda<Action>(block)行程LamdaExpression,最终调用。
3)基本算术方法
表达式树封装了一些基本的计算。
ParameterExpression number = Expression.Parameter(typeof(int), "number");BlockExpression myBlock = Expression.Block( new[] {number}, Expression.Assign(number, Expression.Constant(2)), Expression.AddAssign(number, Expression.Constant(6)), Expression.SubtractAssign(number,Expression.Constant(4)), Expression.MultiplyAssign(number, Expression.Constant(3)), Expression.DivideAssign(number, Expression.Constant(2)), Expression.ModuloAssign(number, Expression.Constant(5))); Expression3.总结> myAction = Expression.Lambda >(myBlock);Console.WriteLine(myAction.Compile()());Console.ReadKey();
表达式树封装一些逻辑,在编译时运行,在实际开发时使用频率较低,主要是调试起来不是很方便,而且对于大多数不熟悉的人来说,看懂不是特别容易。作为.NET技术的一部分,了解下很有必要,毕竟技术都是触类旁通的。