如何正确反映基接口方法

Kon*_*nov 13 c# reflection inheritance interface

我通过Reflection调查了2个接口和2个类:

  • IParent
  • IChild - 源自IParent
  • 孩子 - 来自父母

对我来说奇怪的是,当我通过对IChild类型的反思时,我找不到IParent方法.

应用于Child类型的相同代码按预期工作 - 反射显示Parent方法.

interface IParent
{
     void ParentMethod();
}

interface IChild : IParent
{
     void ChildMethod();
}

class Parent 
{
     public void ParentMethod(){}
}

class Child : Parent
{
     public void ChildMethod(){}
}

void Main()
{
    //investigate derived interface
     Type t = typeof(IChild);
     var info = t.GetMethod("ChildMethod");//ok
     Console.WriteLine(info); 
     info = t.GetMethod("ParentMethod");//returns null!
     Console.WriteLine(info); 
     //investigate derived class
     t = typeof(Child);
     info = t.GetMethod("ChildMethod");//ok
     Console.WriteLine(info);
     info = t.GetMethod("ParentMethod");//ok
     Console.WriteLine(info);
}
Run Code Online (Sandbox Code Playgroud)

请解释一下这种行为?

是否有任何解决方法可以从派生接口的类型中反映基接口的方法?

MaL*_*Lio 11

如果您正在处理接口,请使用

t.GetInterfaces()
Run Code Online (Sandbox Code Playgroud)

然后你可以检查上面返回的类型的方法.

按名称查找接口成员是不可靠的,请注意,虽然在C#接口成员无法在实现时重命名,但在CLR中可能会修改名称.(IDisposable.Dispose()有时会重命名为Close).在il中有一条叫做的指令.implements可以让人改变名字.我相信VB.Net也有这个功能.


dar*_*yal 10

虽然,我们使用接口的方式与使用继承相同(":"); 接口不是继承的; 他们将被实施.在这种情况下; 继承与实现混淆,因为它们是使用相同的运算符(":")定义的.

作为总结; IA : IBA:IA手段; 任何实施IA的类都应实施IB.在这种情况下; A应实施IA和IB.

A:B表示一个类继承B类; 它没有实现.

这里的混淆源于使用相同的运算符(":").

检查此页面界面继承


Dav*_*son 5

接口基接口(在本例中IParent是基接口IChild)是显式基接口.继承是接口的一个不幸的词,因为类,结构和其他接口永远不会从接口继承,它们只是实现基接口定义的契约.

当你派生IChild出来时IParent(注意我没有说继承),它没有定义ParentMethod方法,它只是说任何实现我的东西,也必须实现IParent.

它反映实际类型时的工作原因是因为实现接口实际上确实在类型本身中定义了方法签名,而接口则不然.

这是由编译器称为接口映射的过程引起的,接口映射定义为在实现类或结构中定位接口成员的过程,但接口本身不会发生这种情况.

当您反映接口时,不会发生接口映射,因此仅反映接口本身.

Type t = typeof(IChild);
Run Code Online (Sandbox Code Playgroud)

类型信息仅包含明确的类型信息IChild.

Type t = typeof(Child);
Run Code Online (Sandbox Code Playgroud)

这里确实发生了接口映射的过程.当您反映Child命名方法的类型时,将ParentMethod检查每个基本接口,直到找到匹配项.

这部分语言设计.您可以在C#编程语言(第四版)的第13.1.4节或ECMA规范的第20.1.2节中阅读更多相关内容.

你可以通过进行接口重新实现来解决它,但它需要一些额外的代码.

interface IParent
{
    void ParentMethod();
}

interface IChild
{
    new void ParentMethod(); // Reimplement IParent.ParentMethod()
    void ChildMethod();
}
Run Code Online (Sandbox Code Playgroud)

这会奏效.

Type t = typeof(IChild);
MethodInfo mi = t.GetMethod("ParentMethod");
Run Code Online (Sandbox Code Playgroud)

由于接口重新实现,IChild现在包含一个方法签名ParentMethod.