2016-07-31 4 views
4

Я пытался выпустить следующий код как код IL во время выполнения.InvalidProgramException (Недействительный код IL)?

class TestObject { 
     public int Hello {get;set;} 
     public int Test {get;set;} 
    } 

    static TestObject test(BinaryReader reader) { 
     var a = new TestObject(); 
     a.Hello = reader.ReadInt32(); 
     a.Test = reader.ReadInt32(); 
     return a; 
    } 

LINQPad показывает:

test: 
IL_0000: nop   
IL_0001: newobj  UserQuery+TestObject..ctor 
IL_0006: stloc.0  // a 
IL_0007: ldloc.0  // a 
IL_0008: ldarg.0  
IL_0009: callvirt System.IO.BinaryReader.ReadInt32 
IL_000E: callvirt UserQuery+TestObject.set_Hello 
IL_0013: nop   
IL_0014: ldloc.0  // a 
IL_0015: ldarg.0  
IL_0016: callvirt System.IO.BinaryReader.ReadInt32 
IL_001B: callvirt UserQuery+TestObject.set_Test 
IL_0020: nop   
IL_0021: ldloc.0  // a 
IL_0022: stloc.1  
IL_0023: br.s  IL_0025 
IL_0025: ldloc.1  
IL_0026: ret   

Попытка воспроизвести его с C#:

 var method = new DynamicMethod("DynamicCreate", typeof(TestSubject), new Type[] {typeof(BinaryReader)}, 
      typeof(TestSubject).Module); 
     var il = method.GetILGenerator(); 

     var properties = from property in typeof(TestSubject).GetProperties() 
      let orderAttribute = 
       property.GetCustomAttributes(typeof(OrderAttribute), false).SingleOrDefault() as OrderAttribute 
      orderby orderAttribute.Order 
      select property; 

     il.Emit(OpCodes.Nop); 
     il.Emit(OpCodes.Newobj, typeof(TestSubject).GetConstructors()[0]); // pushes a new instance of testsubject on the stack 
     il.Emit(OpCodes.Stloc_0); // pop the instance to local variable 0 
     foreach (var prop in properties) 
     { 
      il.Emit(OpCodes.Ldloc_0); // load local variable 0 
      il.Emit(OpCodes.Ldarg_0); // load argument 0 (the binary reader) 
      il.Emit(OpCodes.Callvirt, typeof(BinaryReader).GetMethod("ReadInt32", BindingFlags.Public | BindingFlags.Instance)); // call the binary reader method (ReadInt32) 
      il.Emit(OpCodes.Callvirt, prop.SetMethod); // call the setter of the property (instance of local variable 0 and return value of readint32) 
      il.Emit(OpCodes.Nop); 
     } 
     il.Emit(OpCodes.Ldloc_0); 
     il.Emit(OpCodes.Stloc_1); 
     var label = il.DefineLabel(); 
     il.Emit(OpCodes.Br_S, label); 
     il.MarkLabel(label); 
     il.Emit(OpCodes.Ldloc_1); // push the test subject instance 
     il.Emit(OpCodes.Ret); // and return 

     var generator = (Load)method.CreateDelegate(typeof(Load)); 
     var reader = new BinaryReader(new MemoryStream(new byte[] {1, 2, 3, 4, 0, 0, 0, 1})); 
     var test = generator(reader); // exception here 

TestSubject класс:

public class TestSubject 
{ 

    [Order] 
    public int Test1 { get; set; } 

    [Order] 
    public int Test2 { get; set; } 

} 

Давая мне следующее исключение:

System.InvalidProgramException { "Die Common Language Runtime Шляпа Эйн ungültiges Programm gefunden."}

Что случилось с этим?

ответ

3

Вам необходимо объявить местных жителей, прежде чем использовать их. Кроме того, код можно упростить (IL был создан в сборке отладки).

il.DeclareLocal(typeof(TestSubject)); 

il.Emit(OpCodes.Newobj, typeof(TestSubject).GetConstructors()[0]); // pushes a new instance of testsubject on the stack 
il.Emit(OpCodes.Stloc_0); // store the instance in local variable 0 
foreach (var prop in properties) 
{ 
    il.Emit(OpCodes.Ldloc_0); // load local variable 0 
    il.Emit(OpCodes.Ldarg_0); // load argument 0 (the binary reader) 
    il.Emit(OpCodes.Callvirt, typeof(BinaryReader).GetMethod("ReadInt32", BindingFlags.Public | BindingFlags.Instance)); // call the binary reader method (ReadInt32) 
    il.Emit(OpCodes.Callvirt, prop.SetMethod); // call the setter of the property (instance of local variable 0 and return value of readint32) 
} 
il.Emit(OpCodes.Ldloc_0); // push the test subject instance 
il.Emit(OpCodes.Ret); // and return 
+0

Это похоже на меня. Но, как упоминал @usr, я начал работать с деревьями выражений. И я люблю это. Этот вопрос имел хороший учебный эффект для меня. – AmazingTurtle

1

Вы не определили местных жителей.

Кроме того, ИЛ здесь из выхода режима отладки. Это немного сложнее, чем необходимо.

Рефлекторный выброс почти устарел (по-прежнему необходим для некоторых случаев). Гораздо проще генерировать такой код, используя деревья выражений. Удалите весь этот код и замените его деревьями выражений.

Смежные вопросы