2016-11-30 47 views
1

我試圖讓使用ILGenerator.Emit的ILGenerator的Emit:負載的PropertyInfo有

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; 
    } 
} 

這是我到目前爲止已經在做這IL代碼,並有一些併發症的方法參數:

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); 
    } 

它給了我以下異常: - >預計類型:System.Type,收到類型:System

System.String是由以下給出的屬性類型:pi.PropertyType;

我在做什麼錯?提前

+0

你能提供完整的代碼和完全的例外? – thehennyy

+0

什麼給你一個例外?哪裏? Emit幾乎不會檢查你在做什麼(它只是「寫入字節」),所以要確保你發出的是有意義的。它不會牽着你的手。並添加一個實際編譯和顯示您的問題的最小示例*,否則我們可以提供猜測。 – Luaan

回答

2

由於作爲thehennyy評論,如果你能不能給我們完整的代碼,我們將能幫助更好。我想在這裏幫助,因爲我猜你想要做什麼。

所以我基於你的C#代碼。據我所知,你想創建一個方法,獲取類型的屬性(在你的情況)和foreach他們,獲得一些基於類型的價值。

下面是這個類型的第一個屬性的代碼片段。要完成需要發出循環的代碼,或者像您在問題中所寫的那樣,循環使用C#代碼中的屬性並逐個發出每個屬性的代碼。

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(); 
} 

如果我們Foo類型如下:

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

而且GenerateVar看起來是這樣的:

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

它將打印5

+0

非常感謝!這正是我所需要的。 –