I’m trying to use Reflection.Emit to emit a class that will inherit from multiple interfaces at run-time, and I cannot know which interfaces ahead of time.
As per MSDN/TypeBuilder.DefineMethodOverride:
To override a method of a base class or to implement a method of an
interface, simply emit a method with the same name and signature as
the method to be overridden or implemented
Here’s my code that overrides an interface method:
private void OverrideMethod(TypeBuilder typeBuilder,
Type interfaceToOverride,
MethodInfo methodToOverride)
{
// Create the method stub
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
methodToOverride.Name,
MethodAttributes.Public
| MethodAttributes.HideBySig
| MethodAttributes.NewSlot
| MethodAttributes.Virtual
| MethodAttributes.Final,
CallingConventions.HasThis,
methodToOverride.ReturnType,
methodToOverride.GetParameters().Select(p => p.ParameterType).ToArray()
);
// Implement the overriding method
ILGenerator il = methodBuilder.GetILGenerator();
// ... a bunch of calls to il.Emit ...
// Return
il.Emit(OpCodes.Ret);
}
This works, except when I inherit from two interfaces who both have a method with the same name. Obviously this is because I’m not giving a fully-qualified name for the method. I’m not sure how to do this properly.
Changing methodToOverride.Name to interfaceToOverride.FullName + "." + methodToOverride.Name did not work: I get an error when emitting, “TypeLoadException: class does not have implementation.
Using DefineMethodOverride partially worked, but for some reason did not when I tested it against nested interfaces. Also, the documentation linked above explicitly says not to do this.
What’s the right approach to get around this issue?
The proper way to do this is to define a method named
<InterfaceName>.<MethodName>and then callTypeBuilder.DefineMethodOverride.In your case, method body name is
<InterfaceName>.<MethodName>, while method declaration name is<MethodName>. So it’s fine to useTypeBuilder.DefineMethodOverride.Example usage:
Note
Actually, you can define your method (using
TypeBuilder.DefineMethod) with any name. But it should differ from<MethodName>and you must callTypeBuilder.DefineMethodOverrideto “link” method body with method declaration.