【问题标题】:C# 4.0: Expression trees vs. CodeDomC# 4.0:表达式树与 CodeDom
【发布时间】:2010-07-17 11:38:18
【问题描述】:

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

【问题讨论】:

    标签: c# expression-trees codedom


    【解决方案1】:

    表达式树与(例如)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,那么另一种选择是运行时生成代码作为字符串。然后通过CSharpCodeProvider 进行编译。有部分核心运行时执行此操作 (XmlSerializerIIRC)。


    总结一下:

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

    【讨论】:

      【解决方案2】:

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

      如果您想向应用程序添加脚本,请使用 CodeDom。如果你想做非常高级的反射之类的,使用表达式树,但我不推荐它。

      【讨论】: