Загрузка и выполнение DynamicMethod из byte массива
От: qlat  
Дата: 15.07.13 12:39
Оценка:
Цель сохранить байт-код объекта DynamicMethod, и при следующем запуске программы загрузить и выполнить

1. Этап получение байт-кода

Пример
using System.Reflection;
using System.Reflection.Emit;

void f()
{
DynamicMethod d = new DynamicMethod("xxx", typeof(void), null);

ILGenerator il = d.GetILGenerator();
int idx = il.DeclareLocal(typeof(string)).LocalIndex;

il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldstr, "Hellow world");
il.Emit(OpCodes.Stloc, idx);
il.Emit(OpCodes.Ldloc, idx);

Type[] t = new Type [1] { typeof(string) };

MethodInfo mi = typeof(Console).GetMethod("WriteLine", t );
Console.WriteLine(mi.MetadataToken.ToString());

il.Emit(OpCodes.Call, mi);
il.Emit(OpCodes.Nop);
mi = typeof(Console).GetMethod("ReadLine");
il.Emit(OpCodes.Call, mi);
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ret);

MethodBody mb = d.GetMethodBody();
byte[] src = mb.GetILAsByteArray();

/*
var ilgen = d.GetILGenerator();
var fiBytes = il.GetType().BaseType.GetField("m_ILStream", BindingFlags.Instance | BindingFlags.NonPublic);
var fiLength = il.GetType().BaseType.GetField("m_length", BindingFlags.Instance | BindingFlags.NonPublic);
byte[] code = fiBytes.GetValue(ilgen) as byte[];
int cnt = (int)fiLength.GetValue(ilgen);
byte[] src = new byte[cnt];
Buffer.BlockCopy(code, 0, src, 0, cnt);
*/
}

На строке MethodBody mb = d.GetMethodBody();
возникает Exception — Операция является недопустимой из-за текущего состояния объекта.
Байт-код можно получить другим кодом (см. комментарии), но хочется понять, почему нельзя воспользоваться стандартным решением

2. Как скорректировать байт-код при следующем запуске, чтобы он корректно выполнялся (т.к. в байт-коде указываются фактические ссылки на методы, поля, свойства, строки, которые при новом запуске могут иметь другие адреса)?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.