表达式树和 CodeDom 有什么区别?我应该在哪种情况下使用哪个?
2 回答
表达式树与(例如)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
方法信息1
等"abc"
。
codedom 映射到code。这都是关于语句等的,与您编写常规代码的方式非常相似。codedom 最常见的用途是代码生成,作为工具的一部分。您可以将其用于动态编译,但说实话它更难。我不是粉丝。一个不错的功能是代码域树可能适用于多种语言。
这里的另一个竞争者应该是DynamicMethod
和/或ILGenerator
。这不会映射到 AST(表达式),也不能用于生成源代码(codedom),但允许完全访问 MSIL 工具。当然,它也需要您从堆栈等方面进行思考,但它对于元编程非常高效和有效。
如果ILGenerator
太硬核,并且 codedom 是 PITA,那么另一种选择是将代码运行时生成为 string。然后通过它CSharpCodeProvider
来编译它。核心运行时的某些部分可以执行此操作(XmlSerializer
IIRC)。
所以总结一下:
- 元编程:
ILGenerator
或CSharpCodeProvider
;也在Expression
4.0 中(但这在 3.5 中非常有限) - 处理 AST:
Expression
- 运行时解析:
Expression
- 多种语言的代码生成:code-dom
表达式树用于构建表达式。在运行时创建源代码。CodeDom 用于编译源代码。它必须存在才能构建它。表达式树更灵活,但更难使用。
如果要向应用程序添加脚本,请使用 CodeDom。如果您想做非常高级的反射之类的,请使用表达式树,但我不推荐它。