【问题标题】:How do I determine which interface is referenced by an explicitly-implemented MethodInfo object?如何确定显式实现的 MethodInfo 对象引用了哪个接口?
【发布时间】:2010-12-30 01:29:01
【问题描述】:

我有一个MethodInfo 对象,它表示一个显式实现的接口方法,如下所示。

MethodInfo GetMethod()
{
    return typeof(List<>).GetMethod(
        "System.Collections.IEnumerable.GetEnumerator",
        BindingFlags.Instance | BindingFlags.NonPublic);
}

如何查询这个MethodInfo对象来获得它实现的接口类型,一个代表System.Collections.IEnumerableType对象? InterfaceMapping 结构提供逆操作,获取实现给定接口的类型的MethodInfo 对象,所以这不起作用。

请注意,这是一个人为的示例,因为我可以清楚地解析此信息的方法名称。如果可能的话,我想避免这样做。

【问题讨论】:

    标签: .net reflection interface methodinfo explicit-interface


    【解决方案1】:

    试试MethodInfo.DeclaringType

    【讨论】:

    • 这不适用于显式实现的接口方法。它将返回实现接口方法的类型,而不是接口类型。
    【解决方案2】:

    我不知道这样做的直接方法,但是您显然可以反向使用 InterfaceMapping:遍历由方法的声明类型实现的所有接口,检查该方法是否在该接口的接口映射中:

    foreach (Type itf in method.DeclaringType.GetInterfaces())
    {
      if (method.DeclaringType.GetInterfaceMap(itf).TargetMethods.Any(m => m == method))
      {
        Console.WriteLine("match: " + itf.Name);
      }
    }
    

    虽然这看起来有点低效,但大多数类型实现的接口数量很少,这应该没什么大不了的。欣赏它不是非常优雅!

    【讨论】:

    • 这可能是完成搜索的唯一方法,并且有额外的好处是可以找到由单个方法实现的所有接口方法。
    【解决方案3】:

    抱歉我的第一个答案,起初我尝试通过InterfaceMap 结构获取方法,而 that 结构中的方法实际上 do 将接口报告为DeclaringType。然后我对其进行了修补,并没有意识到使用您发布的获取MethodInfo的方法巧妙地破坏了它。

    不过,好处在于,这种细微的差异导致人们意识到接口方法的MethodInfo 和实现方法的MethodInfo 实际上并不是同一个方法。经过进一步思考,我实际上很确定您想做的事情不可能可靠地完成。

    C# 中的显式接口实现与它在 CLR 中的实际工作方式相比有点语法糖。在其他语言中,单个具体方法可以实现多个接口方法,就像具体类可以实现多个接口类型一样。例如,在 VB.NET 中,这样做是完全合法的:

    Public Overrides Function Baz() As String Implements IFoo.Foo, IBar.Bar
    

    这里你有一个明确地实现了两个接口方法的方法。如果有可能得到原始的接口类——甚至是原始的接口方法——你会得到哪一个?如何解决歧义?

    我不是 CLR 内部的专家,但我相信接口映射是单向的。当您隐式或显式地实现一个接口或方法时,编译器会创建一个映射 from 接口 to 实现,这就是它处理针对界面。

    认为 C# 生成的方法名称几乎是巧合。虽然方法名是System.Collections.IEnumerable.GetEnumerator,但实际上只是一个名字,实际上并没有任何关于System.Collections.IEnumerable的信息编码在方法本身中。

    【讨论】:

    • 感谢您的解释。我还注意到,当一个方法显式映射到一个接口方法时,它只需要在签名中匹配,而不是按名称匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    相关资源
    最近更新 更多