如何从使用 Reflection.Emit 生成的类中的变量调用函数

本文关键字:变量 函数 调用 Emit Reflection | 更新日期: 2023-09-27 18:35:41

>我正在用这个创建一个动态类型:

AssemblyName assemblyName = new AssemblyName("LunarDynamicAssembly");
AssemblyBuilder _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder _moduleBuilder = _assembly.DefineDynamicModule("DynamicModule", true);
TypeBuilder typeBuilder = _moduleBuilder.DefineType(original.Name + "Proxy", TypeAttributes.Public | TypeAttributes.Class, original, new Type[] { typeof(IProxy) });
// - This function only implements the IProxy interface and returns the private variable field.
FieldBuilder _interceptor = ImplementIProxy(typeBuilder);
ConstructorInfo _interceptorConstructor = typeof(Interceptor).GetConstructor(Type.EmptyTypes);
foreach (ConstructorInfo constructorInfo in original.GetConstructors())
{
    //Omitting for brev.
    //Recreating all the constructors and ensuring there's a line
    //_interceptor = new Interceptor();
    //in all of them.
}
foreach (PropertyInfo pInfo in original.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
    MethodInfo getMethod = pInfo.GetGetMethod();
    MethodInfo setMethod = pInfo.GetSetMethod();
    PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(pInfo.Name, pInfo.Attributes, pInfo.PropertyType, null);
    MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot;
    MethodBuilder getBuilder = typeBuilder.DefineMethod(getMethod.Name, attributes, pInfo.PropertyType, null);
    ILGenerator getIL = getBuilder.GetILGenerator();
    // - Issues start here
    getIL.Emit(OpCodes.Ldarg_0);
    getIL.Emit(OpCodes.Ldloc, _interceptor);
    getIL.Emit(OpCodes.Callvirt, typeof(Interceptor).GetMethod("InterceptingFunction"));
    getIL.Emit(OpCodes.Stloc_0);
    getIL.Emit(OpCodes.Ldloc_0);
    getIL.Emit(OpCodes.Ret);
    typeBuilder.DefineMethodOverride(getBuilder, getMethod);
}

InterceptingFunction返回与属性相同的类型。我猜我错过了如何在调用函数之前放置"实例"部分,从我在 ILDasm 中检查的内容来看。我该怎么做?

异常:公共语言运行库检测到无效程序。

编辑)更多信息 执行我尝试生成的函数的 IL 代码(返回 20 部分除外):

// Code size       20 (0x14)
.maxstack  1
.locals init ([0] int32 CS$1$0000)
IL_0000:  nop
IL_0001:  ldarg.0
IL_0002:  ldfld      class [Test]Test.DataAccess.Interceptor Tests.MyClass::_interceptor
IL_0007:  callvirt   instance void [Test]Test.DataAccess.Interceptor::InterceptingFunction()
IL_000c:  nop
IL_000d:  ldc.i4.s   20
IL_000f:  stloc.0
IL_0010:  br.s       IL_0012
IL_0012:  ldloc.0
IL_0013:  ret

如何从使用 Reflection.Emit 生成的类中的变量调用函数

Constrast

getIL.Emit(OpCodes.Ldloc, _interceptor);

ldfld      class [Test]Test.DataAccess.Interceptor Tests.MyClass::_interceptor

ldloc指令用于加载局部变量,要加载字段,需要使用ldfld

也没有声明任何局部变量,但您仍然尝试使用一个局部变量(stloc.0ldloc.0)。尽管在您的情况下,该局部变量是完全不必要的,但您可以将从InterceptingFunction返回的值保留在堆栈上。(工作 IL 这样做是为了帮助调试,我相信这些额外的说明,以及不必要的分支在发布模式下不会出现。