有没有办法将MethodBody(或其他反射技术)转换为System.Linq.Expressions.Expression树?
答案 0 :(得分:1)
是的,有可能......但据我所知,它还没有完成。
如果有人 知道了一个将方法解组成表达式树的库,请告诉我,或者编辑上面的语句。
您需要做的最困难的部分是编写CIL反编译器。也就是说,您需要将相当低级别的CIL指令(概念上以堆栈计算机为目标)转换为更高级别的表达式。
Redgate的Reflector或Telerik的JustDecompile等工具就是这样做的,但它们不是构建表达式树,而是显示源代码;你可以说他们更进了一步,因为表达树基本上仍然与语言无关。
一些值得注意的案例,其中特别棘手:
您必须处理没有预定义Expression
树节点的CIL指令的情况;比方说,tail.call
或cpblk
(我在这里猜一点)。也就是说,您必须创建自定义表达式树节点类型;当.Compile()
表达式树可能成为问题时将它们编译回可执行方法,因为表达式树编译器试图将自定义节点分解为标准节点。如果那是不可能的,那么你就不能再编译表达式树了,你只能检查它。
您是否会尝试识别某些高级构造(例如C#using
块)并尝试为其构建(自定义)表达式树节点?请记住,C#using
在编译期间会分解为try…finally { someObj.Dispose(); }
,因此如果您反映在method body's CIL instructions和{{3}上,那么您可能会看到而不是using
}}
因此,一般来说,期望您需要能够“识别”某些代码模式并将它们概括为更高级别的概念。
答案 1 :(得分:1)
确实可以,请参阅DelegateDecompiler:
https://github.com/hazzik/DelegateDecompiler
注意:我不隶属于此项目
编辑
以下是项目采用的基本方法:
以下是项目中反编译方法体的代码片段:
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));
}
}
答案 2 :(得分:0)
不,没有。
你基本上要求更简单的版本Reflector。