【问题标题】:Reverse of Expression<Func<T,TResult>>.Compile()?表达式的反转<Func<T,TResult>>.Compile()?
【发布时间】:2010-09-28 05:04:59
【问题描述】:

既然我们可以:

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();

也就是我想得到Func对应的Expression。有可能吗?

【问题讨论】:

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


【解决方案1】:

delegate 实例没有什么神奇的Decompile(),除了解构 IL(也许使用 mono.cecil)。如果你想要一个表达式树,你必须开始一个表达式树,Expression&lt;Func&lt;int, bool&gt;&gt; througout 也是如此。

作为一种极端情况,您可以从委托的.MethodMethodInfo)和.Targetarg0)获取基本方法委托信息 - 但是,对于大多数情况涉及 lambda 或匿名方法,这将指向捕获类上的编译器生成方法,因此对您没有太大帮助。它几乎仅限于以下场景:

Func<string,int> parse = int.Parse;

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 没有。如果你将x=&gt;x&gt;5 传递给Decompile,它将传递一个Expression。我想反编译一个Func&lt;int,bool&gt;,而不知道它的内容。
    • 正如马克所说,这是不可能的。我只是想我会发布一个最接近反编译的示例。
    • 是的,当我看到您的回答时,我知道您正在发布最接近的示例。但别人不这么认为,他投了反对票:(
    【解决方案3】:

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

    虽然它对于Compile() 的结果可能无法正常工作,因为它是DynamicMethod 并且获得它的IL 并不简单。但是,如果您为 DynamicMethod 实现自己的 IManagedMethod 实现,它应该可以工作。

    我计划实现DynamicMethod 适配器,但还不知道何时。

    【讨论】:

    • 太棒了。我会试试看。非常感谢。
    【解决方案4】:

    您不能反编译委托,但您当然可以创建一个简单地调用委托的新表达式树:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多