利用 MethodBody类的GetILAsByteArray方法可以获取到返回字节数组的MSIL的body。然后再去解析此字节数组, 可以得到MSIL,然后你再去解析MSIL,你就可以得到你想到source code,这样就可以做小的反....,以下是代码的实现....
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; namespace Timwi.ILReaderExample { public class ILReader { public class Instruction { public int StartOffset { get; private set; } public OpCode OpCode { get; private set; } public long? Argument { get; private set; } public Instruction(int startOffset, OpCode opCode, long? argument) { StartOffset = startOffset; OpCode = opCode; Argument = argument; } public override string ToString() { return OpCode.ToString() + (Argument == null ? string.Empty : " " + Argument.Value); } } private Dictionary<short, OpCode> _opCodeList; public ILReader() { _opCodeList = typeof(OpCodes).GetFields().Where(f => f.FieldType == typeof(OpCode)).Select(f => (OpCode)f.GetValue(null)).ToDictionary(o => o.Value); } public IEnumerable<Instruction> ReadIL(MethodBase method) { MethodBody body = method.GetMethodBody(); if (body == null) yield break; int offset = 0; byte[] il = body.GetILAsByteArray(); while (offset < il.Length) { int startOffset = offset; byte opCodeByte = il[offset]; short opCodeValue = opCodeByte; offset++; // If it's an extended opcode then grab the second byte. The 0xFE prefix codes aren't marked as prefix operators though. if (opCodeValue == 0xFE || _opCodeList[opCodeValue].OpCodeType == OpCodeType.Prefix) { opCodeValue = (short)((opCodeValue << 8) + il[offset]); offset++; } OpCode code = _opCodeList[opCodeValue]; Int64? argument = null; int argumentSize = 4; if (code.OperandType == OperandType.InlineNone) argumentSize = 0; else if (code.OperandType == OperandType.ShortInlineBrTarget || code.OperandType == OperandType.ShortInlineI || code.OperandType == OperandType.ShortInlineVar) argumentSize = 1; else if (code.OperandType == OperandType.InlineVar) argumentSize = 2; else if (code.OperandType == OperandType.InlineI8 || code.OperandType == OperandType.InlineR) argumentSize = 8; else if (code.OperandType == OperandType.InlineSwitch) { long num = il[offset] + (il[offset + 1] << 8) + (il[offset + 2] << 16) + (il[offset + 3] << 24); argumentSize = (int)(4 * num + 4); } // This does not currently handle the 'switch' instruction meaningfully. if (argumentSize > 0) { Int64 arg = 0; for (int i = 0; i < argumentSize; ++i) { Int64 v = il[offset + i]; arg += v << (i * 8); } argument = arg; offset += argumentSize; } yield return new Instruction(startOffset, code, argument); } } } public static partial class Program { public static void Main(string[] args) { var reader = new ILReader(); var module = typeof(Program).Module; foreach (var instruction in reader.ReadIL(typeof(Program).GetMethod("Main"))) { string arg = instruction.Argument.ToString(); if (instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldflda || instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldsflda || instruction.OpCode == OpCodes.Stfld) arg = module.ResolveField((int)instruction.Argument).Name; else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt) arg = module.ResolveMethod((int)instruction.Argument).Name; else if (instruction.OpCode == OpCodes.Newobj) // This displays the type whose constructor is being called, but you can also determine the specific constructor and find out about its parameter types arg = module.ResolveMethod((int)instruction.Argument).DeclaringType.FullName; else if (instruction.OpCode == OpCodes.Ldtoken) arg = module.ResolveMember((int)instruction.Argument).Name; else if (instruction.OpCode == OpCodes.Ldstr) arg = module.ResolveString((int)instruction.Argument); else if (instruction.OpCode == OpCodes.Constrained || instruction.OpCode == OpCodes.Box) arg = module.ResolveType((int)instruction.Argument).FullName; else if (instruction.OpCode == OpCodes.Switch) // For the 'switch' instruction, the "instruction.Argument" is meaningless. You'll need extra code to handle this. arg = "?"; Console.WriteLine(instruction.OpCode + " " + arg); } Console.ReadLine(); } } }