因为我们可以:
Expression<Func<int, bool>> predicate = x => x > 5;
var result = Enumerable.Range(0,10).Where(predicate.Compile());
我怎么能:
Func<int,bool> predicate = x => x > 5;
Expression<Func<int,bool>> exp = predicate.Decompile();
也就是说,我希望获得Expression
的相应Func
。有可能吗?
答案 0 :(得分:7)
委托实例没有魔法Decompile()
,缺少解构IL(可能使用mono.cecil)。如果你想要一个表达式树,你必须用表达式树开始,所以要Expression<Func<int, bool>>
througout。
作为边缘案例,您可以从代理人.Method
(MethodInfo
)和.Target
(arg0
获取基本方法委托信息但是,对于涉及lambda或匿名方法的大多数情况,这将指向捕获类上的compiler-generate方法,因此对您没有多大帮助。它几乎局限于:
Func<string,int> parse = int.Parse;
答案 1 :(得分:5)
将lambda传递给接受Expression<>的方法,C#编译器将在运行时传递表达式树。但是,这仅在您直接传递lambda时有效,而不是在您尝试传递从lambda创建的委托实例时。
var exp = Decompile(x => x > 5);
public Expression<Func<int, bool>> Decompile(Expression<Func<int, bool>> exp)
{
return exp;
}
我发现的用于反编译委托实例的最接近的选项在Jean {Baptiste Evain的this博客文章中有详细说明,他在Mono团队工作。他使用优秀的Mono.Cecil项目将IL反编译为自定义AST,然后将其尽可能地映射到LINQ表达式中。
答案 2 :(得分:3)
您可以尝试使用我的库:
https://github.com/ashmind/expressive
虽然它可能不适用于Compile()
的结果,因为它是DynamicMethod
并且获得它的IL并不简单。但是,如果您为IManagedMethod
实施自己的DynamicMethod
实施,它应该可以正常运作。
我计划实现DynamicMethod
个适配器,但还不知道什么时候。
答案 3 :(得分:1)
您不能反编译委托,但您当然可以创建一个新的表达式树,只需调用委托:
Func<int, bool> predicate = x => x > 5;
Expression<Func<int, bool>> exp = x => predicate(x);