表达式的反转<func <t,tresult>&gt; .Compile()?</func <t,tresult>

时间:2010-09-28 05:04:59

标签: c# .net linq lambda expression-trees

因为我们可以:

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。有可能吗?

4 个答案:

答案 0 :(得分:7)

委托实例没有魔法Decompile(),缺少解构IL(可能使用mono.cecil)。如果你想要一个表达式树,你必须用表达式树开始,所以要Expression<Func<int, bool>> througout。

作为边缘案例,您可以从代理人.MethodMethodInfo)和.Targetarg0获取基本方法委托信息但是,对于涉及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);