C#4.0:表达式树与CodeDom

Yar*_*veh 9 c# codedom expression-trees

表达式树和CodeDom之间有什么区别?我应该在哪种情况下使用哪个?

Mar*_*ell 25

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

((a + 2) / b)
Run Code Online (Sandbox Code Playgroud)

那是:

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

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

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

Foo(x => x.SomeMethod(1, "abc"));
Run Code Online (Sandbox Code Playgroud)

并提取SomeMethod方法-INFO,1"abc"


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


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


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


总结一下:

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