3

我正在尝试使用 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.NameinterfaceToOverride.FullName + "." + methodToOverride.Name无效:发出时出现错误,“TypeLoadException:类没有实现。

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

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

4

1 回答 1

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

于 2013-02-04T21:32:09.427 回答