我正在尝试使用Reflection.Emit来发出一个在运行时从多个接口继承的类,我无法提前知道哪些接口。
根据MSDN/TypeBuilder.DefineMethodOverride:
覆盖基类的方法或实现方法 接口,只需发出一个名称和签名相同的方法 要覆盖或实施的方法
这是我的代码覆盖了一个接口方法:
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);
}
这是有效的,除非我从两个都具有相同名称的方法的接口继承。显然这是因为我没有给出该方法的完全限定名称。我不确定如何正确地做到这一点。
将methodToOverride.Name
更改为interfaceToOverride.FullName + "." + methodToOverride.Name
不起作用:发出时出错,“TypeLoadException:class没有实现。
使用DefineMethodOverride
部分工作,但出于某种原因,当我针对嵌套接口测试它时没有。此外,上面链接的文档明确表示不这样做。
解决此问题的正确方法是什么?
答案 0 :(得分:2)
执行此操作的正确方法是定义名为<InterfaceName>.<MethodName>
的方法,然后调用TypeBuilder.DefineMethodOverride
。
当一个方法体和一个。时,使用了的DefineMethodOverride方法 方法声明具有不同的名称。
在您的情况下,方法正文名称为<InterfaceName>.<MethodName>
,而方法声明名称为<MethodName>
。所以可以使用TypeBuilder.DefineMethodOverride
。
使用示例:
private void OverrideMethod(TypeBuilder typeBuilder,
Type interfaceToOverride,
MethodInfo methodToOverride)
{
// Create the method stub
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
/* Change method name here */
string.Format("{0}.{1}", interfaceToOverride.FullName,
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);
// And define a methodimpl, which consists of a pair of metadata tokens.
// One token points to an implementation, and the other token points
// to a declaration that the body implements
typeBuilder.DefineMethodOverride(methodBuilder, methodToOverride);
}
注意强>
实际上,您可以使用任何名称定义您的方法(使用TypeBuilder.DefineMethod
)。但它应该与<MethodName>
不同,并且您必须调用TypeBuilder.DefineMethodOverride
以使用方法声明“链接”方法正文。