.net 4.0 将MethodBody转换为表达式树
有没有办法将MethodBody(或其他反射技术)转换为System.Linq.Expressions.Expression树 没有.net 4.0 将MethodBody转换为表达式树,.net-4.0,linq-expressions,.net 4.0,Linq Expressions,有没有办法将MethodBody(或其他反射技术)转换为System.Linq.Expressions.Expression树 没有 您基本上要求的是更简单的版本。是的,有可能。。。但据我所知,还没有完成 如果有人知道某个库将方法反编译为表达式树,请告诉我,或编辑上述语句 您必须做的最困难的部分是编写反编译器。也就是说,您需要将相当低级的CIL指令(概念上以堆栈机器为目标)转换为更高级的表达式 诸如Redgate或Telerik之类的工具就是这样做的,但它们不是构建表达式树,而是显示源代码;你可
您基本上要求的是更简单的版本。是的,有可能。。。但据我所知,还没有完成 如果有人知道某个库将方法反编译为表达式树,请告诉我,或编辑上述语句 您必须做的最困难的部分是编写反编译器。也就是说,您需要将相当低级的CIL指令(概念上以堆栈机器为目标)转换为更高级的表达式 诸如Redgate或Telerik之类的工具就是这样做的,但它们不是构建表达式树,而是显示源代码;你可以说它们更进一步,因为表达式树基本上仍然是语言不可知的 一些值得注意的情况下,这会变得特别棘手:
- 您必须处理没有预定义的
树节点的CIL指令的情况;比如说,表达式
,或者tail.call
(我在这里猜一点)。也就是说,您必须创建自定义表达式树节点类型;当您cpblk
表达式树时,将它们编译回可执行方法可能是一个问题,因为表达式树编译器试图将自定义节点分解为标准节点。如果这是不可能的,那么您就不能再编译表达式树了,您只能检查它.Compile()
- 您是否会尝试使用块识别某些高级构造,例如C#
,并尝试为其构建(自定义)表达式树节点?请记住,在编译过程中,C#
分解为相当于使用
,因此如果您在和上进行反思,您可能会看到这一点,而不是try…finally{someObj.Dispose()}
因此,一般来说,您需要能够“识别”某些代码模式,并将它们总结为更高级别的概念使用
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,是的。谢谢大家的反馈。在这种情况下,我不确定应该包括什么,因为我作为一个整体链接的项目需要回答。也许可以总结一下方法?