Running this under .NET 8.
IJoinable<T1, T2>
already exists in the codebase as a generic interface. It declares one method, T2 Join(T1 value)
. The types being used for the type parameters (lType
, rType
, joinedType
) are TypeBuilder variables that have been dynamically generated at runtime.
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")!);
When I call joinType.GetMethod()
on that last line, it throws NotSupportedException
, because somehow it ended up inside of System.Reflection.Emit.TypeBuilderInstantiation.GetMethodImpl()
, whose entire method body is to throw NotSupportedException
.
If that doesn't work, what's the right way to do this?
To perform operations involving Reflection.Emit and generics, there are three somewhat hidden, yet in plain sight, static methods on TypeBuilder
:
TypeBuilder.GetMethod
TypeBuilder.GetConstructor
TypeBuilder.GetField
These methods operate on TypeBuilderInstantiation
objects. Therefore, the call that fails using the classic GetMethod
method needs to be replaced with one like this:
var genericMethod = TypeBuilder.GetMethod(joinType, typeof(IJoinable<,>).GetMethod("Join"));
Actually, I think the documentation for these methods is quite good (TypeBuilder.GetMethod). However, they deviate from the pattern established by other parts of the Reflection.Emit API, making them somewhat difficult to find.