2015-04-09 5 views
1

Здесь C# код:Как перевести ИЛ на Emit заявления?

public class Calc1 : ICalculator 
{ 
    public int Calculate(int x, int y) 
    { 
     return x + y; 
    } 
} 

Вот IL:

.method public hidebysig newslot virtual final 
    instance int32 Calculate(int32 x, 
           int32 y) cil managed 
{ 
    // Code size  9 (0x9) 
    .maxstack 2 
    .locals init ([0] int32 CS$1$0000) 
    IL_0000: nop 
    IL_0001: ldarg.1 
    IL_0002: ldarg.2 
    IL_0003: add 
    IL_0004: stloc.0 
    IL_0005: br.s  IL_0007 
    IL_0007: ldloc.0 
    IL_0008: ret 
} // end of method Calc1::Calculate 

Как я могу перевести IL выше Выделяют заявления? Вот моя попытка перевода строк одна за другой, но получила «System.InvalidProgramException».

 string methodName = "Calculate"; 

     MethodBuilder getFieldMethod = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), new Type[] { typeof(int), typeof(int) }); 
     ILGenerator methodIL = getFieldMethod.GetILGenerator(); 

     Label iL0007Label = methodIL.DefineLabel(); 

     methodIL.Emit(OpCodes.Nop); 
     methodIL.Emit(OpCodes.Ldarg_1); 
     methodIL.Emit(OpCodes.Ldarg_2); 
     methodIL.Emit(OpCodes.Add); 
     methodIL.Emit(OpCodes.Stloc_0); 
     methodIL.Emit(OpCodes.Br_S, iL0007Label); 

     methodIL.MarkLabel(iL0007Label); 
     methodIL.Emit(OpCodes.Ldloc_0); 
     methodIL.Emit(OpCodes.Ret); 

Что случилось с моими высказываниями Emit?

ответ

2

Вы забыли объявить локальную переменную:

ILGenerator methodIL = getFieldMethod.GetILGenerator(); 

methodIL.DeclareLocal(typeof(int)); // THIS ONE! 

Label iL0007Label = methodIL.DefineLabel(); 

И технически вы забыли MethodAttributes.Final, но я не знаю, если вы хотите, чтобы добавить его.

Обратите внимание, что коды операций, которые вы получили, вероятно, предназначены для сборки отладки. Если вы хотите посмотреть коды операций, я предлагаю использовать сборки релизов, которые используют меньше кодов операций.

ILGenerator methodIL = getFieldMethod.GetILGenerator(); 
methodIL.Emit(OpCodes.Ldarg_1); 
methodIL.Emit(OpCodes.Ldarg_2); 
methodIL.Emit(OpCodes.Add); 
methodIL.Emit(OpCodes.Ret); 

достаточно для того, что вы хотите, даже не используя локальную переменную.

+0

Вы абсолютно БЕСПЛАТНО! Большое спасибо, Ксанатос. Вы спасли меня много времени. – Zach

0

Я не очень много работал над Reflection.Emit, но когда я обычно делал это, я использовал команду PEVerify в командной строке VS. Он сообщает, что не так с созданной сборкой. Надеюсь, поможет.

+0

Большое спасибо за информацию. – Zach