根据方法名获取方法Body Content
利用 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(); } } }
分类:
C# Code
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?