表达式的反转<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。
作为边缘情况,您可以从委托的.Target
( MethodInfo
)和.Target
( arg0
)获取基本方法委托信息 – 但是,对于涉及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);