5

有没有办法将 MethodBody(或其他反射技术)转换为 System.Linq.Expressions.Expression 树?

4

3 回答 3

2

确实有可能,见 DelegateDecompiler:

https://github.com/hazzik/DelegateDecompiler

注意:我隶属于这个项目

编辑

以下是该项目采用的基本方法:

  1. 获取要转换的方法的 MethodInfo
  2. 使用 methodInfo.GetMethodBody 获取 MethodBody 对象。其中包含 MSIL 以及有关参数和本地信息的信息
  3. 仔细阅读说明,检查操作码,并构建适当的表达式
  4. 将它们捆绑在一起并返回优化的表达式

这是项目中反编译方法体的代码片段:

 public class MethodBodyDecompiler
    {
        readonly IList<Address> args;
        readonly VariableInfo[] locals;
        readonly MethodInfo method;

        public MethodBodyDecompiler(MethodInfo method)
        {
            this.method = method;
            var parameters = method.GetParameters();
            if (method.IsStatic)
                args = parameters
                    .Select(p => (Address) Expression.Parameter(p.ParameterType, p.Name))
                    .ToList();
            else
                args = new[] {(Address) Expression.Parameter(method.DeclaringType, "this")}
                    .Union(parameters.Select(p => (Address) Expression.Parameter(p.ParameterType, p.Name)))
                    .ToList();

            var body = method.GetMethodBody();
            var addresses = new VariableInfo[body.LocalVariables.Count];
            for (int i = 0; i < addresses.Length; i++)
            {
                addresses[i] = new VariableInfo(body.LocalVariables[i].LocalType);
            }
            locals = addresses.ToArray();
        }

        public LambdaExpression Decompile()
        {
            var instructions = method.GetInstructions();
            var ex = Processor.Process(locals, args, instructions.First(), method.ReturnType);
            return Expression.Lambda(new OptimizeExpressionVisitor().Visit(ex), args.Select(x => (ParameterExpression) x.Expression));
        }
    }
于 2015-06-09T16:59:37.850 回答
1

不,没有。

您基本上是在要求一个更简单的Reflector版本。

于 2010-09-01T14:57:08.913 回答
1

是的,有可能……但据我所知,还没有完成。

如果有人知道将方法反编译为表达式树的库,请告诉我,或编辑上述语句。

您要做的最困难的部分是编写CIL反编译器。也就是说,您需要将相当低级的 CIL 指令(在概念上以堆栈机器为目标)转换为更高级别的表达式。

Redgate的Reflector或 Telerik 的JustDecompile等工具就是这样做的,但它们不是构建表达式树,而是显示源代码;您可以说它们更进一步,因为表达式树基本上仍然与语言无关。

一些值得注意的情况会变得特别棘手:

  • 您将不得不处理不存在预定义Expression树节点的 CIL 指令的情况;比方说,tail.callcpblk(我在这里猜一点)。也就是说,您必须创建自定义表达式树节点类型;当您使用表达式树时,将它们编译回可执行方法.Compile()可能是一个问题,因为表达式树编译器会尝试将自定义节点分解为标准节点。如果那不可能,那么您将无法再编译表达式树,您只能检查它。

  • 您会尝试识别某些高级构造(例如 C#using块)并尝试为其构建(自定义)表达式树节点吗?请记住,C#在编译期间using分解为等价物try…finally { someObj.Dispose(); },因此您可能会看到这种情况,而不是using反映在方法主体的 CIL 指令异常处理子句中。

    因此,一般来说,期望您能够“识别”某些代码模式并将它们总结为更高级别的概念。

于 2012-08-16T10:33:15.767 回答