在 .NET 8 下运行此程序。
IJoinable<T1, T2>
已经作为通用接口存在于代码库中。它声明了一种方法,T2 Join(T1 value)
。用于类型参数的类型(lType
、rType
、joinedType
)是在运行时动态生成的 TypeBuilder 变量。
var joinType = typeof(IJoinable<,>).MakeGenericType(rType, joinedType);
lType.AddInterfaceImplementation(joinType);
var joinMethod = lType.DefineMethod("Join", MethodAttributes.Public | MethodAttributes.Virtual, joinedType, [rType]);
var gen = joinMethod.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, ctor);
gen.Emit(OpCodes.Ret);
lType.DefineMethodOverride(joinMethod, joinType.GetMethod("Join")!);
当我在最后一行调用
joinType.GetMethod()
时,它会抛出 NotSupportedException
,因为不知何故它最终出现在 System.Reflection.Emit.TypeBuilderInstantiation.GetMethodImpl()
内部,而其整个方法体就是抛出 NotSupportedException
。
如果这不起作用,正确的方法是什么?
为了执行涉及 Reflection.Emit 和泛型的操作,
TypeBuilder
上存在三个有些隐藏但显而易见的静态方法:
TypeBuilder.GetMethod
TypeBuilder.GetConstructor
TypeBuilder.GetField
这些方法作用于
TypeBuilderInstantiation
对象。因此,使用经典 GetMethod
方法失败的调用需要替换为如下所示:
var genericMethod = TypeBuilder.GetMethod(joinType, typeof(IJoinable<,>).GetMethod("Join"));
实际上,我认为这些方法的文档非常好(TypeBuilder.GetMethod)。然而,它们偏离了 Reflection.Emit API 其他部分建立的模式,使得它们有点难以找到。