As a bit of a novelty, I\'m trying to see how different the IL from light weight code generated at runtime looks vs code generated by the VS compiler, as I noticed that VS c
Yeah, doesn't work, the method is generated by Reflection.Emit. The IL is stored in the MethodBuilder's ILGenerator. You can dig it out but you have to be pretty desperate. Reflection is needed to get to the internal and private members. This worked on .NET 3.5SP1:
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
...
var mtype = compiled.Method.GetType();
var fiOwner = mtype.GetField("m_owner", BindingFlags.Instance | BindingFlags.NonPublic);
var dynMethod = fiOwner.GetValue(compiled.Method) as DynamicMethod;
var ilgen = dynMethod.GetILGenerator();
var fiBytes = ilgen.GetType().GetField("m_ILStream", BindingFlags.Instance | BindingFlags.NonPublic);
var fiLength = ilgen.GetType().GetField("m_length", BindingFlags.Instance | BindingFlags.NonPublic);
byte[] il = fiBytes.GetValue(ilgen) as byte[];
int cnt = (int)fiLength.GetValue(ilgen);
// Dump <cnt> bytes from <il>
//...
On .NET 4.0 you'll have to use ilgen.GetType().BaseType.GetField(...) because the IL generator was changed, DynamicILGenerator, derived from ILGenerator.
Based off Hans Passant's work I was able to dig a little deeper there appears to be a method that you should call, called BakeByteArray
so the following works::
var dynMethod = fiOwner.GetValue(compiled.Method) as DynamicMethod;
var ilgen =dynamicMethod.GetILGenerator();
byte[] il = ilgen.GetType().GetMethod("BakeByteArray", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(ilgen, null) as byte[];
This certainly helps, but I still have no way to resolve VariableInfo's
just yet which is something that would help in my work.
The current solutions here aren't addressing the current situation in .NET 4 very well. You can use either DynamicILInfo
or ILGenerator
to create the dynamic method, but the solutions listed here do not work with DynamicILInfo
dynamic methods at all.
Whether you use the DynamicILInfo
method of generating IL or the ILGenerator
method, the IL bytecode ends up in DynamicMethod.m_resolver.m_code. You don't have to check both methods and it's a less complex solution.
This is the version you should be using:
public static byte[] GetILBytes(DynamicMethod dynamicMethod)
{
var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
return (byte[])resolver.GetType().GetField("m_code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(resolver);
}
See this answer for more helper methods and a solution for the DynamicMethod token resolution issue.
The ILReader here should work.
ILVisualizer 2010 Solution