我尝试使用 ILGenerator.Emit
在IL中创建此代码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;
}
}
这是我迄今为止所做的,并且有一些并发症:
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,Received类型:System.String
System.String是由以下内容给出的属性类型: pi.PropertyType;
我做错了什么?
提前致谢
答案 0 :(得分:2)
正如thehennyy评论,如果你能给我们完整的代码,我们可以帮助更好。我试图在这里提供帮助,因为我猜你想做什么。
所以我基于你的C#代码。据我所知,你想创建一个获取类型属性的方法(在你的情况下为Foo)和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