Ultimately, the expression tree's API is really just a more familiar API over relection.emit and thus they are effectively equivalent, though I do believe there are many things that you cannot do in expression trees that you can via direct reflection.emit.
Reflection.Emit is the fastest overall, but in the same way that a for loop is faster than foreach in general. There are many scenarios where you can write code that executes faster using reflection.emit than you can using the expression api, but in most cases they should come out equivalent.
Now, the expression API does lend itself to being a slightly better way of doing things for a couple of reasons.
- It's composable in a simpler way than using direct reflection.emit. You can take an expression tree and re-write it to add in some logic much easier than you can than with using direct IL
- Optimizations may be added in the future that you may not understand that would not have occurred when using direction reflection.emit.
So ultimately, I would say it's a wash. If it's really critical and you know reflection.emit quite well, you can usually take some shortcuts in IL that you won't get using the expression API, but other than that, in general usage, they should be fairly equivalent.