1

我想尝试一下它是如何System.Reflection.Emit工作的,但最终我遇到了一些问题。我想创建(使用Emit)一些简单的类,如下所示:

using System;

namespace emit
{
    class Builder
    {
        private String name;

        public Builder(String builderName)
        {
            name = builderName;
        }

        public override int GetHashCode()
        {
            return name.GetHashCode();
        }

        public override string ToString()
        {
            return this.name;
        }
    }
}

我已经完成了一些教程,并且设法创建了动态库。我已经将该库保存在我的磁盘上,然后使用反射加载它。我能够过滤它的类型、构造函数和方法。我还成功调用了传递所需的构造函数string。然而,当我尝试调用任何方法时出现问题 -System.Reflection.TargetInvocationException被抛出。

这是我的实现方式GetHashCode()

MethodBuilder mHashCode = tBuilder.DefineMethod("GetHashCode",
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                CallingConventions.HasThis, typeof(System.Int32), null);
            mHashCode.SetImplementationFlags(MethodImplAttributes.Managed);
            ILGenerator mHashGenerator = mHashCode.GetILGenerator();

            MethodInfo defaultHashCode = typeof(object).GetMethod("GetHashCode");

            mHashGenerator.Emit(OpCodes.Ldfld, simpleName);
            mHashGenerator.Emit(OpCodes.Callvirt, defaultHashCode);
            mHashGenerator.Emit(OpCodes.Ret);

tBuilderTypeBuilder我在创造。

保存程序集并对其进行调查后,ILDSASM如下所示: 在此处输入图像描述

EditModule.dll在此处输入图像描述

不幸的是,这个方法不会调用。这是代码:

                Type dType = asm.GetTypes()[0];
                ConstructorInfo dConstructor = dType.GetConstructor(new Type[] { typeof(string) });
                object dObject = dConstructor.Invoke(new object[] { "Pawel" });
                MethodInfo[] dMethods = dType.GetMethods();
                foreach(var mi in dMethods)
                {
                    Console.WriteLine(mi.Name);
                }
                //method with `0` index is `GetHashCode()`
                dMethods[0].Invoke(dObject, null);

有谁知道我可能做错了什么?

4

1 回答 1

1

这个片段

mHashGenerator.Emit(OpCodes.Ldfld, simpleName);

正在尝试获取字段值,但您忘记了这样做需要一个实例。由于您正在构建的方法是一个实例方法,是该方法的隐藏的第一个参数,因此要获取您的值this.name应该使用以下

mHashGenerator.Emit(OpCodes.Ldarg_0);
mHashGenerator.Emit(OpCodes.Ldfld, simpleName);
于 2016-01-12T15:33:55.790 回答