Is there a way to convert a MethodBody (or other Reflection 开发者_如何学Ctechnique) into a System.Linq.Expressions.Expression tree?
It is indeed possible, see DelegateDecompiler:
https://github.com/hazzik/DelegateDecompiler
NOTE: I am not affiliated with this project
Edit
Here is the basic approach that the project takes:
- Get MethodInfo for the method you want to convert
- Use methodInfo.GetMethodBody to get a MethodBody object. This contains, among other things, the MSIL and info on arguments and locals
- Go through the instructions, examine the opcodes, and build the appropriate Expressions
- Tie it all together and return an optimized Expression
Here is a code snippet from the project that decompiles a method body:
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));
}
}
No, there isn't.
You're basically asking for a somewhat simpler version of Reflector.
Yes, it is possible... but it hasn't been done yet, as far as I know.
If anyone does know of a library that de-compiles methods to expression trees, please let me know, or edit the above statement.
The most difficult part of what you would have to do is write a CIL de-compiler. That is, you would need to translate the fairly low-level CIL instructions (which conceptually target a stack machine) into much higher-level expressions.
Tools such as Redgate's Reflector or Telerik's JustDecompile do just that, but instead of building expression trees, they display source code; you could say they go one step further, since expression trees are basically still language-agnostic.
Some notable cases where this would get especially tricky:
You would have to deal with cases of CIL instructions for which no pre-defined
Expression
tree node exists; let's say,tail.call
, orcpblk
(I'm guessing a little here). That is, you'd have to create custom expression tree node types; having them compiled back into an executable method when you.Compile()
the expression tree might be an issue, because the expression tree compiler tries to break down custom nodes into standard nodes. If that is not possible, then you cannot compile the expression tree any more, you could only inspect it.Would you try to recognise certain high-level constructs, such as a C#
using
block, and try to build a (custom) expression tree node for it? Remember that C#using
breaks down to the equivalent oftry…finally { someObj.Dispose(); }
during compilation, so that is what you might see instead ofusing
if you reflected over the method body's CIL instructions and exception handling clauses.Thus, in general, expect that you need to be able to "recognise" certain code patterns and summarise them into a higher-level concept.
精彩评论