1. 程式人生 > >TypeInfo和Type的區別與選擇

TypeInfo和Type的區別與選擇

概念 

TypeInfo出現於.net framework 4.5之後,這次調整用於區分兩個概念:“reference”和“definition”。

reference is a shallow representation of something

definition is  a rich representation of something

例如System.Reflection.Assembly就代表了一個“definition” ,而System.Reflection.AssemblyName就代表了一個“reference

在未區分這兩種概念之前,System.Type

是這兩種概念的混合,通過一個Type例項,既可以獲得該型別的“Name、Assembly、……”,也可以獲得該型別的“NestTypes、Fields、Properties、Methods、Constructors、Events……”。這也導致了當我們獲得一個Type的時候,就把它全部的資訊都載入到了記憶體中,但是很多情況下,這並不是我們想要看到的。舉例如下:

public MyClass:BaseClass{

}

//獲得MyClass的型別物件

Type t=MyClass.GetType();

 在.net framework 4中,獲得型別物件時,同時獲得了基類(BaseClass)的型別物件,同時包括基類物件的“reference

”和“definition”,因此需要把基類所在的程式集也載入進來。

在.net framework 4.5中,如下程式碼:

Type baseType = MyClass.GetType().GetTypeInfo().BaseType;

 在獲得型別物件時,只獲得了基類的"reference"

使用

在明確概念後,具體什麼屬性和方法屬於"definition",什麼屬性和方法屬於"reference",我並沒有很清晰,以下只是做一個粗糙的說明。

最簡單的理解就是:System.Reflection.TypeInfo中的屬性和方法即是"definition",而去除掉System.Type中與TypeInfo重合的部分,剩下的即是"reference

"。

簡單比較一下可以發現:

public class Type:MemberInfo
{
    public bool Is*();
    public MemberInfo[] GetMembers();
    public virtual MemberInfo[] GetMember(string name, BindingFlags bindingAttr);
}

public class TypeInfo:Type
{
    public IEnumerable<MemberInfo> DeclaredMembers{get;}
}

下面針對以上程式碼,從以下幾個角度進行說明:

型別繼承:TypeInfo繼承自Type,但實際上

右圖才是真正實現了概念分離的程式碼結構,現在的設計,只是為了相容之前的版本

返回內容:

Get*()返回的是當前型別定義的MemberInfo以及其基類的public型別的MemberInfo

Declear*屬性返回的是當前型別定義的Member Info

返回資料型別:

Get*()返回的是Array型別

Declear*屬性返回的是IEnumerable<>型別,此型別具有延遲載入的功能,因為如果要返回Array型別,必須將Array填滿後返回,而IList和IEnumerable只是實現了一個狀態機,這裡沒有使用IList的原因是,IEnumerable更加簡潔

 返回資料過濾

Get*()方法含有BindingFlags引數,用來選擇返回的MemberInfo是Public還是Static...

Declear*()的方法並不含有BindingFlags引數,因此需要使用LINQ進行查詢過濾