如何正确反映基本接口方法

本文关键字:接口 方法 何正确 | 更新日期: 2023-09-27 18:33:56

我有 2 个接口和 2 个类,我通过反射进行研究:

  • IParent
  • IChild - 源自 IParent
  • 父母
  • 子项 - 派生自父项

对我来说奇怪的是,当我查看IChild类型的反射时,我找不到IParent方法。

应用于子类型的相同代码按预期工作 - 反射显示父方法。

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

请解释一下这种行为?

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

如何正确反映基本接口方法

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

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

A:B 表示 A 类继承 B 类;它不实现。

此处的混淆源于使用相同的运算符 (":"(。

检查此页面接口继承

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

t.GetInterfaces()

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

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

接口

的基本接口(在本例中IParentIChild的基本接口(是显式的基本接口。继承对于接口来说是一个不幸的词,因为类、结构和其他接口从不从接口继承,它们只是实现基接口定义的协定。

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

当您反映实际类型时,它之所以有效,是因为实现接口实际上确实在类型本身中定义了该方法签名,而接口并非如此。

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

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

Type t = typeof(IChild);

类型信息将仅包含显式有关IChild的类型信息。

Type t = typeof(Child);

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

这部分语言设计。您可以在 C# 编程语言(第四版(的第 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 的方法签名。

相关文章: