c# - 发出一个类覆盖两个具有相同名称的接口(interface)方法

标签 c# .net reflection.emit

我正在尝试使用 Reflection.Emit 发出一个将在运行时从多个接口(interface)继承的类,但我无法提前知道哪些接口(interface)。

根据 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

这是我重写接口(interface)方法的代码:

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);
}

这是有效的,除非我从两个接口(interface)继承,这两个接口(interface)都有一个同名的方法。显然,这是因为我没有为该方法提供完全限定的名称。我不确定如何正确执行此操作。

methodToOverride.Name 更改为 interfaceToOverride.FullName + "."+ methodToOverride.Name 不起作用:发出时出现错误,“TypeLoadException:类没有实现。

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

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

最佳答案

正确的方法是定义一个名为 <InterfaceName>.<MethodName> 的方法然后调用 TypeBuilder.DefineMethodOverride .

The DefineMethodOverride method is used when a method body and a method declaration have different names.

在您的例子中,方法体名称是 <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 将方法体与方法声明“链接”起来。

关于c# - 发出一个类覆盖两个具有相同名称的接口(interface)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14693103/

相关文章:

c# - 是否可以使用 oData.net 实现微服务

c# - ReaderWriterLockSlim 和计时器

c# - LINQ 表达式和这个

wcf - LinqPad 如何支持 WCF 数据服务?

c# - 带资源文件的 asp.net 核心 (resx)

C#求最大公约数

c# - 使用 MSTest 和 Fakes (Shim) 填充 .Net System.Windows.Forms.Screen 构造函数以进行单元测试

c# - Reflection.Emit 与 CodeDOM

c# - 从 Internet 下载大文件时,如何阻止 C# 应用程序的 UI 变得无响应

c# - ODAC 12c 和 Entity Framework 6