15

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

  • 父母
  • 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);
}

请解释这种行为?

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

4

3 回答 3

11

虽然,我们使用接口的方式与使用继承的方式相同(“:”);接口不被继承;它们将得到执行。在这种情况下; 继承与实现混淆,因为它们是使用相同的运算符(“:”)定义的。

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

A:B表示A类继承B类;它没有实施。

这里的混乱源于使用相同的运算符(“:”)。

检查此页面接口继承

于 2012-05-11T12:12:30.697 回答
11

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

t.GetInterfaces()

然后您可以检查上面返回的类型的方法。

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

于 2012-05-11T12:37:05.650 回答
6

接口的接口(在这种情况下IParent是 的基接口IChild)是显式基接口。继承对于接口来说是一个不幸的词,因为类、结构和其他接口永远不会从接口继承,它们只是实现基本接口定义的契约。

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

当您反映实际类型时,它起作用的原因是因为实现接口实际上确实在类型本身中定义了该方法签名,而接口并非如此。

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

反射接口时,不会发生接口映射,因此只反射接口本身。

Type t = typeof(IChild);

类型信息将仅包含关于 的明确类型信息IChild

Type t = typeof(Child);

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

这部分是语言设计。您可以在 C# Programming Language (Fourth Edition) 的第 13.1.4 节或 ECMA 规范的第 20.1.2 节中阅读更多相关信息。

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

interface IParent
{
    void ParentMethod();
}

interface IChild
{
    new void ParentMethod(); // Reimplement IParent.ParentMethod()
    void ChildMethod();
}

这会奏效。

Type t = typeof(IChild);
MethodInfo mi = t.GetMethod("ParentMethod");

由于接口重新实现,IChild现在包含ParentMethod.

于 2012-05-11T12:19:08.223 回答