c#, reflection.emit 努力
c#, reflection.emit trying hard
我想试试 System.Reflection.Emit
是如何工作的,但最终我遇到了一些问题。我想创建(使用 Emit
)一些简单的 class,像这样:
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);
tBuilder
是我正在创建的 TypeBuilder
。
保存程序集并使用 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);
有没有人知道我可能做错了什么?
这个片段
mHashGenerator.Emit(OpCodes.Ldfld, simpleName);
正在尝试获取字段值,但您忘记了为此需要一个 实例 。由于您正在构建的方法是一个实例方法,this 是该方法的隐藏第一个参数,因此要获取 this.name
的值,您应该使用以下
mHashGenerator.Emit(OpCodes.Ldarg_0);
mHashGenerator.Emit(OpCodes.Ldfld, simpleName);
我想试试 System.Reflection.Emit
是如何工作的,但最终我遇到了一些问题。我想创建(使用 Emit
)一些简单的 class,像这样:
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);
tBuilder
是我正在创建的 TypeBuilder
。
保存程序集并使用 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);
有没有人知道我可能做错了什么?
这个片段
mHashGenerator.Emit(OpCodes.Ldfld, simpleName);
正在尝试获取字段值,但您忘记了为此需要一个 实例 。由于您正在构建的方法是一个实例方法,this 是该方法的隐藏第一个参数,因此要获取 this.name
的值,您应该使用以下
mHashGenerator.Emit(OpCodes.Ldarg_0);
mHashGenerator.Emit(OpCodes.Ldfld, simpleName);