2009-11-23 69 views
4

當在接口類型上反映時,我只獲取特定類型的成員,而不是繼承成員。爲什麼繼承接口的成員不能使用反射?

在這個過於簡單化的例子,該程序只打印「名稱」,而不是「ItemNumber」,「名稱」爲我所期望的:

using System; 

public interface IBasicItem 
{ 
    string ItemNumber { get; set; } 
} 

public interface IItem : IBasicItem 
{ 
    string Name { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var type = typeof (IItem); 
     foreach (var prop in type.GetProperties()) 
      Console.WriteLine(prop.Name); 
    } 
} 

這背後的原理是什麼?當我從基礎接口繼承時,我說我的接口的任何實現都必須實現繼承的成員。換句話說,IItem is-a IBasicItem。那麼,爲什麼繼承的成員不會使用反射?

回答

10

我認爲這正是Phil Haack剛纔所寫的內容。

從ECMA-335公共語言基礎結構規範:

11年9月8日接口類型派生接口類型可以要求 實現的一個或多個其它 接口。對接口類型實現 支持的任何類型 也將實現對該接口指定的任何 必需接口的支持。這是從對象 類型繼承不同有兩種方式:

  • 對象類型形成單個繼承樹;接口類型不是 。
  • 對象類型繼承指定如何實現繼承; 所需接口不要,因爲 接口沒有定義 的實現。所需的接口 指定了實現對象類型爲 支持的附加合同。

高亮顯示最後 差異,考慮一個接口, IFoo的,有一個方法。接口IBar從 派生,它要求支持IBar的任何對象類型 也支持IFoo。 它並沒有說IBar本身具有哪些方法 。

引用自: http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx

+0

Doh ...今天早上我可以告訴我很困。 +1爲正確的答案。 – 2009-11-23 14:39:13

1

這是因爲你用的接口工作。接口不會得到與類相同的繼承結構。

如果你有一個實現這些接口的類,你會看到正確的鏈(假設你使用「BindingFlags.FlattenHierarchy」)。

嘗試創建一個實現較低級別接口的類,並且您應該看到您要查找的內容。

1

這是因爲你沒有要求你想知道的信息。換句話說,由於你的繼承屬性與你從接口獲得的屬性有不同的含義,你必須以不同的方式訪問它們。

因此,你可以像這樣通過反射訪問:

foreach (var iface in type.GetInterfaces()) 
{ 
    foreach (var prop in iface.GetProperties()) 
    { 
    Console.WriteLine(iface.Name +"-"+ prop.Name); 
    } 
} 

由於類繼承比接口規格不同,它似乎是合乎邏輯以不同的方式訪問它們。

6

考慮這個問題的一個好方法是接口沒有像繼承類一樣的「繼承」。繼承意味着「是一種」關係,但接口「繼承」實際上意味着「需要提供這種服務」的關係。

當我們說

interface IEnumerator<T> : IDisposable 

就是我們要說的是沒有那麼多的「序列統計員是一種一次性的東西」爲「如果你提供的服務的枚舉,則必須提供的Dispose服務」。

現在是否更有意義?

相關問題