C#4.0:表达式树与CodeDom

Expression树和CodeDom有什么区别? 我应该在哪种情况下使用哪个?

表达式树与(例如) AST有许多共同之处。 它不直接映射到代码,但非常适合从算法构造。 例如,如果要解析公式:

((a + 2) / b) 

那是:

 ParameterExpression a = ..., b = ... var body = Expression.Divide( Expression.Add(a, Expression.Constant(2)), b); var lambda = Expression.Lambda(body,a,b); // optionally with generics 

实际上,我已经完成这个,使用构建对象树的解析器,通过“访问者”实现生成完整表达的对象。 在.NET 4.0中,更丰富的表达式树支持使得支持大多数场景成为可能,并根据需要进行编译。

表达式的另一个关键用途是您可以在运行时解构它们,因此在您的代码中您可能具有:

 Foo(x => x.SomeMethod(1, "abc")); 

并提取SomeMethod方法SomeMethod1"abc"等。


codedom映射到代码 。 它完全与语句等有关,与编写常规代码的方式非常相似。 编码器的最常见用途是用于代码生成,作为工具的一部分。 您可以将它用于动态编译,但说实话它更难。 我不是粉丝。 好的function是编码树可能适用于多种语言。


这里的另一个竞争者应该是DynamicMethod和/或ILGenerator 。 这不会映射到AST(表达式),也不能用于生成源代码(codedom),但允许完全访问MSIL工具。 当然,它还需要您考虑堆栈等,但它对元编程非常有效和高效。


如果ILGenerator太硬核,而且encodeom是PITA,那么另一种选择是将代码运行时生成为字符串 。 然后通过CSharpCodeProvider传递它来编译它。 核心运行时的某些部分可以执行此操作( XmlSerializer IIRC)。


总结一下:

  • 元编程: ILGeneratorCSharpCodeProvider ; 4.0中的Expression (但这在3.5中非常有限)
  • 处理AST: Expression
  • 在运行时解析: Expression
  • 多种语言的代码生成:代码

表达式树用于构建表达式。 在运行时创建源代码。 CodeDom用于编译源代码。 它必须存在才能构建它。 表达式树更灵活,但使用起来更难。

如果要向应用程序添加脚本,请使用CodeDom。 如果你想做非常高级的reflection和喜欢,使用表达式树,但我不推荐它。