Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse of Expression<Func<T,TResult>>.Compile()?

Since we can:

Expression<Func<int, bool>> predicate = x => x > 5;
var result = Enumerable.Range(0,10).Where(predicate.Compile());

How can I:

Func<int,bool> predicate = x => x > 5;
Expression<Func<int,bool>> exp = predicate.Decompile();

That is, I want to get the corresponding Expression of the Func. Is it possible?

like image 663
Cheng Chen Avatar asked Sep 28 '10 05:09

Cheng Chen


2 Answers

There is no magic Decompile() for a delegate instance, short of deconstructing the IL (perhaps with mono.cecil). If you want an expression tree, you'll have to start with an expression tree, so have Expression<Func<int, bool>> througout.

As an edge case, you can get basic method delegate information from the delegate's .Method (the MethodInfo) and .Target (the arg0) - however, for most scenarios involving a lambda or anonymous method this will point at the compiler-generate method on the capture class, so won't really help you much. It is pretty much limited to scenarios like:

Func<string,int> parse = int.Parse;
like image 180
Marc Gravell Avatar answered Nov 07 '22 18:11

Marc Gravell


Pass the lambda to a method that accepts an Expression<> and the C# compiler will pass you an expression tree at runtime. However this only works if you pass the lambda directly, not if you try to pass a delegate instance created from a lambda.

var exp = Decompile(x => x > 5);

public Expression<Func<int, bool>> Decompile(Expression<Func<int, bool>> exp)
{
    return exp;
}

The closest option I've found for decompiling a delegate instance is detailed in this blog post from Jean-Baptiste Evain who works on the Mono team. He uses the excellent Mono.Cecil project to decompile the IL into a custom AST, then he maps it as best as possible into LINQ expressions.

like image 5
Nathan Baulch Avatar answered Nov 07 '22 20:11

Nathan Baulch