表达式的反转<Func >。编译()?

既然我们可以:

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

我怎么能够:

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

也就是说,我想得到相应的Func Expression 。 可能吗?

对于委托实例没有神奇的Decompile() ,没有解构IL(可能使用mono.cecil)。 如果你想要一个表达式树,你必须一个表达式树开始 ,所以让Expression> througout。

作为边缘情况,您可以从委托的.TargetMethodInfo )和.Targetarg0 )获取基本方法委托信息 – 但是,对于涉及lambda或匿名方法的大多数情况,这将指向编译器生成方法捕获类,所以不会真正帮助你。 它几乎局限于以下场景:

 Func parse = int.Parse; 

将lambda传递给接受Expression <>的方法,C#编译器将在运行时传递表达式树。 但是,这仅在您直接传递lambda时有效,而不是在尝试传递从lambda创建的委托实例时。

 var exp = Decompile(x => x > 5); public Expression> Decompile(Expression> exp) { return exp; } 

我发现用于反编译委托实例的最接近的选项在Jean-Baptiste Evain的博客文章中有详细介绍,他在Mono团队工作。 他使用优秀的Mono.Cecil项目将IL反编译为自定义AST,然后将其尽可能地映射到LINQ表达式中。

您可以尝试使用我的库:
https://github.com/ashmind/expressive

虽然它可能不适用于Compile()结果,因为它是一个DynamicMethod并且得到它的IL并不简单。 但是,如果为DynamicMethod实现自己的IManagedMethod实现,它应该可以正常工作。

我打算实现DynamicMethod适配器,但还不知道什么时候。

您无法反编译委托,但您当然可以创建一个只调用委托的新表达式树:

 Func predicate = x => x > 5; Expression> exp = x => predicate(x);