2016-11-30 4 views
1

Ich versuche, diesen Code in IL zu machen mit ILGenerator.EmitILGenerator Emit: Lastproperty hat Methodenparameter

class Foo 
{ 
    ... 
} 

public class TestClass 
{  
    public static void test() 
    { 
     Type t = typeof(Foo); 

     foreach(PropertyInfo p in t.GetProperties()) 
     { 
      GenerateVar(p.PropertyInfo); 
     } 
    } 

    public static object GenerateVar(Type var) 
    { 
     if (var == typeof(Int32)) 
     { 
      return 5; 
     } 
     else if (var == typeof(Char)) 
     { 
      return 'a'; 
     } 

     return null; 
    } 
} 

Dies ist, was ich bisher getan, und hatte einige Komplikationen :

MethodInfo mi = TestClass.GetType().GetMethod("GenerateVar", 
              BindingFlags.Public | 
              BindingFlags.Instance); 

    ILGenerator generator = mb.GetILGenerator(); 

    LocalBuilder propertyType; 
    LocalBuilder TestClass = mb_gen.DeclareLocal(typeof(TestClass)); 

    foreach (PropertyInfo pi in t.GetProperties()) 
    { 
     propertyType = mb_gen.DeclareLocal(pi.PropertyType); 

     //loads into the stack the current PropertyType and the method class 
     generator.Emit(OpCodes.Ldloc, TestClass); 
     generator.Emit(OpCodes.LdLoc, propertyType); 


     //calls GenerateVar(Type var) to get a PropertyType var 
     generator.Emit(OpCodes.Callvirt, mi); 
    } 

Es gibt mir die folgende Ausnahme: ->erwarteten Typ: System.Type, Empfangene Typ: System.String

System.String ist der angegebene Eigenschaftstyp: pi.PropertyType;

Was mache ich falsch?

Vielen Dank im Voraus

+0

Können Sie Ihren vollständigen Code bereitstellen und die vollständige Ausnahme? – thehennyy

+0

Was gibt Ihnen eine Ausnahme? Woher? Emit macht so gut wie keine Kontrolle darüber, was Sie tun (es schreibt nur "Bytes"), also stellen Sie sicher, dass das, was Sie aussenden, Sinn macht. Es wird deine Hand nicht halten. Und fügen Sie ein minimales Beispiel * hinzu, das Ihr Problem * tatsächlich kompiliert und anzeigt, andernfalls können wir nur Vermutungen anbieten. – Luaan

Antwort

2

Als thehennyy Kommentar, wenn Sie uns den vollständigen Code geben können, wir können besser helfen. Ich versuche hier zu helfen, weil ich denke, was du versuchst zu tun.

Also habe ich hier auf Ihrem C# -Code basiert. Wie ich verstehe, möchten Sie eine Methode erstellen, die Eigenschaften des Typs (Foo in Ihrem Fall) und foreach von ihnen erhalten, einen Wert basierend auf Typ erhalten.

Hier ist ein Ausschnitt davon, es für die erste Eigenschaft des Typs zu tun. Um den Code zu vervollständigen, müssen Sie die Schleife ausgeben oder, wie Sie in Ihrer Frage geschrieben haben, die Eigenschaften in Ihrem C# -Code durchgehen und den Code für jede Eigenschaft nacheinander ausgeben.

static void CallGenerateVar() 
{ 
    var dm = new DynamicMethod("CallGenerateVar", typeof(object), Type.EmptyTypes, typeof(TestClass)); 
    MethodInfo generateVarMethod = typeof(TestClass).GetMethod("GenerateVar", BindingFlags.Public | BindingFlags.Instance); 
    var ilGen = dm.GetILGenerator(); 
    var properties = ilGen.DeclareLocal(typeof(PropertyInfo[])); 
    var index = ilGen.DeclareLocal(typeof(int)); 
    var propInfo = ilGen.DeclareLocal(typeof(PropertyInfo)); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldtoken, typeof(Foo)); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public)); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Callvirt, typeof(Type).GetMethod("GetProperties", Type.EmptyTypes)); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Stloc_0); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Stloc_1); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_0); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_1); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Stloc_2); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_0); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ldloc_2); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Callvirt, typeof(PropertyInfo).GetMethod("get_PropertyType", BindingFlags.Instance | BindingFlags.Public)); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Callvirt, generateVarMethod); 
    ilGen.Emit(System.Reflection.Emit.OpCodes.Ret); 

    var del = (Func<object>)dm.CreateDelegate(typeof(Func<object>)); 
    var result = del.Invoke(); 
} 

Bei unserem Foo Typ wie folgt aussieht:

class Foo 
{ 
    public int MyProperty { get; set; } 
} 

Und GenerateVar wie folgt aussieht:

public object GenerateVar(Type var) 
{ 
    if (var == typeof(Int32)) 
    { 
     return 5; 
    } 
    else if (var == typeof(Char)) 
    { 
     return 'a'; 
    } 
    return null; 
} 

Es druckt 5

+0

vielen dank! das war genau das, was ich brauchte. –