【问题标题】:ILGenerator Emit : Load propertyInfo has method parameterILGenerator Emit:加载 propertyInfo 有方法参数
【发布时间】:2016-11-30 14:07:44
【问题描述】:

我正在尝试使用 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,接收类型:System.String

System.String 是由以下给出的属性类型:pi.PropertyType;

我做错了什么?

提前致谢

【问题讨论】:

  • 你能提供你的完整代码和完整的异常吗?
  • 什么给了你一个例外?在哪里? Emit 几乎不会检查您正在做什么(它只是“写入字节”),因此请确保您发出的内容是有意义的。它不会牵你的手。并添加一个实际编译并显示您的问题的最小示例,否则我们只能提供猜测。

标签: c# .net cil reflection.emit propertyinfo


【解决方案1】:

作为 thehennyy 评论,如果您能给我们完整的代码,我们将可以提供更好的帮助。我想在这里提供帮助,因为我猜你想做什么。

所以我在这里基于你的 C# 代码。据我了解,您想创建一个方法来获取类型(在您的情况下为 Foo)和 foreach 的属性,并根据类型获取一些值。

这是针对类型的第一个属性执行此操作的 sn-p。要完成代码,您需要发出循环,或者像您在问题中所写的那样,循环 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

【讨论】:

  • 非常感谢!这正是我所需要的。
猜你喜欢
  • 2018-01-02
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 2018-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多