zoukankan      html  css  js  c++  java
  • 根据方法名获取方法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();
            }
        }
    }

      

  • 相关阅读:
    java工程师要求
    系统架构设计师知识模块
    Mybatis使用训练
    项目—视频直播系统
    [数算]概率
    查看镜像文件
    Hadoop启动命令
    Hadoop启动命令
    HDFS设置配额管理
    HDFS设置配额管理
  • 原文地址:https://www.cnblogs.com/cang/p/4160291.html
Copyright © 2011-2022 走看看