发出一个重写两个同名接口方法的类

本文关键字:接口 方法 重写 一个 两个 | 更新日期: 2023-09-27 17:57:26

我正在尝试使用反射。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:类没有实现。

使用DefineMethodOverride部分起作用,但由于某种原因,当我针对嵌套接口测试它时没有起作用。此外,上面链接的文档明确表示不要这样做。

解决这个问题的正确方法是什么?

发出一个重写两个同名接口方法的类

执行此操作的正确方法是定义一个名为<InterfaceName>.<MethodName>的方法,然后调用TypeBuilder.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以将方法体与方法声明"链接"起来。

相关文章: