如何正确反映基接口方法
我通过Reflection调查了2个接口和2个类:
- IParent
- IChild – 源自IParent
- 亲
- 孩子 – 来自父母
对我来说奇怪的是,当我通过对IChild类型的反思时,我找不到IParent方法。
应用于Child类型的相同代码按预期工作 – reflection显示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); }
请解释一下这种行为?
是否有任何解决方法可以从派生接口的类型中反映基接口的方法?
虽然,我们使用接口的方式与使用inheritance相同(“:”); 接口不是inheritance的; 他们将被实施。 在这种情况下; inheritance与实现混淆,因为它们是使用相同的运算符(“:”)定义的。
作为总结; IA : IB
和A:IA
表示; 任何实施IA的class级都应实施IB。 在这种情况下; A应实施IA和IB。
A:B
表示一个类inheritanceB类; 它没有实现。
这里的混淆源于使用相同的运算符(“:”)。
检查此页面界面inheritance
如果您正在处理接口,请使用
t.GetInterfaces()
然后你可以检查上面返回的类型的方法。
按名称查找接口成员是不可靠的,请注意,虽然在C#接口成员无法在实现时重命名,但在CLR中可能会修改名称。 (IDisposable.Dispose()有时会重命名为Close)。 在il中有一个名为.implements
的指令,允许用户更改名称。 我相信VB.Net也有这个function。
接口的基接口 (在本例中为IParent
是IParent
的基接口)是显式基接口 。 inheritance是接口的一个不幸的词,因为类,结构和其他接口永远不会从接口inheritance ,它们只是实现基接口定义的契约。
当您从IParent
派生IChild
时(注意我没有说inheritance),它没有定义ParentMethod
方法,它只是说任何实现我的东西,也必须实现IParent
。
它反映实际类型时的工作原因是因为实现接口实际上确实在类型本身中定义了方法签名,而接口则不然。
这是由编译器称为接口映射的过程引起的, 接口映射定义为在实现类或结构中定位接口成员的过程,但接口本身不会发生这种情况。
当您反映接口时, 不会发生接口映射,因此仅反映接口本身。
Type t = typeof(IChild);
类型信息将仅包含有关IChild
类型信息。
Type t = typeof(Child);
这里确实发生了接口映射的过程。 当您为名为ParentMethod
的方法反映Child
的类型时,将ParentMethod
每个基本接口,直到找到匹配项。
这部分语言设计。 您可以在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
现在包含IChild
的方法签名。