.net 4.0 将MethodBody转换为表达式树

.net 4.0 将MethodBody转换为表达式树,.net-4.0,linq-expressions,.net 4.0,Linq Expressions,有没有办法将MethodBody(或其他反射技术)转换为System.Linq.Expressions.Expression树 没有 您基本上要求的是更简单的版本。是的,有可能。。。但据我所知,还没有完成 如果有人知道某个库将方法反编译为表达式树,请告诉我,或编辑上述语句 您必须做的最困难的部分是编写反编译器。也就是说,您需要将相当低级的CIL指令(概念上以堆栈机器为目标)转换为更高级的表达式 诸如Redgate或Telerik之类的工具就是这样做的,但它们不是构建表达式树,而是显示源代码;你可

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

没有


您基本上要求的是更简单的版本。

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

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

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

诸如Redgate或Telerik之类的工具就是这样做的,但它们不是构建表达式树,而是显示源代码;你可以说它们更进一步,因为表达式树基本上仍然是语言不可知的

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

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

  • 您是否会尝试使用块识别某些高级构造,例如C#
    ,并尝试为其构建(自定义)表达式树节点?请记住,在编译过程中,C#
    使用
    分解为相当于
    try…finally{someObj.Dispose()}
    ,因此如果您在和上进行反思,您可能会看到这一点,而不是
    使用

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


确实有可能,请参阅DelegateDecompiler:

注:我不属于这个项目

编辑

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

  • 获取要转换的方法的MethodInfo
  • 使用methodInfo.GetMethodBody获取MethodBody对象。这包括,, 除此之外,MSIL和参数及局部变量的信息
  • 仔细阅读说明,检查操作码,并构建适当的表达式
  • 将其全部绑定在一起并返回一个优化的表达式
  • 以下是项目中反编译方法体的代码片段:

     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));
            }
        }
    
    公共类MethodBodyDecompiler
    {
    只读IList args;
    只读变量信息[]局部变量;
    只读MethodInfo方法;
    公共MethodBody反编译器(MethodInfo方法)
    {
    这个方法=方法;
    var parameters=method.GetParameters();
    if(方法IsStatic)
    args=参数
    .Select(p=>(地址)Expression.Parameter(p.ParameterType,p.Name))
    .ToList();
    其他的
    args=new[]{(地址)表达式.参数(method.DeclaringType,“this”)}
    .Union(parameters.Select(p=>(Address)Expression.Parameter(p.ParameterType,p.Name)))
    .ToList();
    var body=method.GetMethodBody();
    var addresses=newvariableinfo[body.LocalVariables.Count];
    for(int i=0;i(ParameterExpression)x.Expression));
    }
    }
    
    您为什么特别想使用
    方法体
    ?还有别的吗?我提到它是因为它是你得到IL字节数组的地方。是的,还有别的东西。您还需要
    MethodBase
    ,因为在这里您可以访问方法签名(参数和返回值的类型);为了构建一个实例,你需要这样做。是Reflector让我怀疑这是否可行。@Chris:如果你重写Reflector,是的。谢谢大家的反馈。在这种情况下,我不确定应该包括什么,因为我作为一个整体链接的项目需要回答。也许可以总结一下方法?