Вам необходимо получить MethodInfo. Вызовите GetMethodBody (), чтобы получить структуру тела метода, а затем вызовите GetILAsByteArray для этого. Преобразуйте этот байтовый массив в поток понятного IL.
Грубо говоря
public static List<Instruction> ReadIL(MethodInfo method)
{
MethodBody body = method.GetMethodBody();
if (body == null)
return null;
var instructions = new List<Instruction>();
int offset = 0;
byte[] il = body.GetILAsByteArray();
while (offset < il.Length)
{
int startOffset = offset;
byte opCodeByte = il[offset];
short opCodeValue = opCodeByte;
// If it's an extended opcode then grab the second byte. The 0xFE
// prefix codes aren't marked as prefix operators though.
if (OpCodeList[opCodeValue].OpCodeType == OpCodeType.Prefix
|| opCodeValue == 0xFE)
{
opCodeValue = (short) ((opCodeValue << 8) + il[offset + 1]);
offset += 1;
}
// Move to the first byte of the argument.
offset += 1;
OpCode code = OpCodeList[opCodeValue];
Int64? argument = null;
if (code.ArgumentSize() > 0)
{
Int64 arg = 0;
Debug.Assert(code.ArgumentSize() <= 8);
for (int i = 0; i < code.ArgumentSize(); ++i)
{
Int64 v = il[offset + i];
arg += v << (i*8);
}
argument = arg;
offset += code.ArgumentSize();
}
var instruction = new Instruction(startOffset, code, argument);
instructions.Add(instruction);
}
return instructions;
}
, где OpCodeList создается через
OpCodeList = new Dictionary<short, OpCode>();
foreach (var opCode in typeof (OpCodes).GetFields()
.Where(f => f.FieldType == typeof (OpCode))
.Select(f => (OpCode) f.GetValue(null)))
{
OpCodeList.Add(opCode.Value, opCode);
}
Затем вы можете определить, какие инструкции являются вызовами свойств IL или поисками переменных-членов, или что вам нужно, и разрешите их затем через GetType (). Module.ResolveField.
(предостерегающий код выше более или менее работал, но был скопирован из более крупного проекта, который я сделал, поэтому, возможно, пропустил мелкие детали).
Редактировать: Размер аргумента - это метод расширения в OpCode, который просто использует справочную таблицу для поиска подходящего значения
public static int ArgumentSize(this OpCode opCode)
{
Dictionary<OperandType, int> operandSizes
= new Dictionary<OperandType, int>()
{
{OperandType.InlineBrTarget, 4},
{OperandType.InlineField, 4},
{OperandType.InlineI, 4},
// etc., etc.
};
return operandSizes[opCode.OperandType];
}
Размеры вы найдете в ECMA 335 , на которые вам также нужно обратить внимание, чтобы найти коды операций, чтобы найти, какие коды операций вы ищете, чтобы найти вызовы, которые вы ищете.