What are the differences between Expression trees and CodeDom? Which should I use for which scenario?
Expression trees are used to build expressions. Creating source code at runtime. CodeDom is used to compile source code. It has to exist before you can build it. Expression trees are more flexible, but a lot harder to use.
If you want to add scripting to your application, use CodeDom. If you want to do very advanced reflection and the likes, use expression trees, but I don't recommend it.
Expression trees have a lot in common with (for example) an AST. It doesn't map directly to code, but is very amenable to construction from algorithms. For example, if you are parsing a formula:
((a + 2) / b)
that is:
ParameterExpression a = ..., b = ...
var body = Expression.Divide(
Expression.Add(a, Expression.Constant(2)),
b);
var lambda = Expression.Lambda(body,a,b); // optionally with generics
In fact, I have done exactly this, using a parser that build an object tree, with objects generating the complete expresion via a "visitor" implementation. In .NET 4.0, the richer expression-tree support makes it possible to support most scenarios, and compile it on demand.
Another key use of expressions is that you can deconstruct them at runtime, so in your code you might have:
Foo(x => x.SomeMethod(1, "abc"));
and extract the SomeMethod
method-info, 1
and "abc"
etc.
codedom maps to code. It is all about statements etc, very similar to how you would write regular code. The most common use of codedom is for code generation, as part of tooling. You can use it for dynamic compilation, but to be honest it is harder. I am not a fan. The nice feature is that a codedom tree might work for multiple languages.
Another contender here should be DynamicMethod
and/or ILGenerator
. This doesn't map to an AST (expression), and can't be used to generate source-code (codedom), but allows full access to the MSIL tools. Of course, it also requires that you think in terms of stacks etc, but it is very efficient and effective for meta-programming.
If ILGenerator
is too hard-core, and codedom is a PITA, then another option is runtime generation of code as a string. Then pass that through CSharpCodeProvider
to compile it. There are parts of the core runtime that do this (XmlSerializer
IIRC).
So to summarise:
- meta-programming:
ILGenerator
orCSharpCodeProvider
; alsoExpression
in 4.0 (but this is quite limited in 3.5) - handling AST:
Expression
- parsing at runtime:
Expression
- code-generation in multiple languages: code-dom