天天看點

入門反射(一)反射Type類擷取Type對象總結

原文: 入門反射(一)

在很多項目的很多地方都發現了一個共同的術語---反射

有時候我在想這是個什麼東西,能幹啥。

這幾天靜下心來,好好地去翻了翻書,看了看别人的部落格。

也自己比着寫了兩個泛型反射方法。還算了解了一小部分,寫個記錄。

上例子代碼:

這是通過反射工廠來建立執行個體:

public static T TFactory<T>() where T : class
{
     Type ty = typeof(T);
     string spaceStr = ty.Namespace; 
     string fullStr = ty.FullName;
     Assembly ass = Assembly.Load(spaceStr); 
     object ob = ass.CreateInstance(fullStr, true);

     return (T)ob; 
}        

這是将Datatable裡的資料反射到LIst集合中:

public static List<T> ToList<T>(this DataTable dt)
{
    if (dt == null || dt.Rows.Count == 0)
    {
        return default(List<T>);
    }

    List<T> list = new List<T>();
    Type type = typeof(T);   
    PropertyInfo[] per = type.GetProperties(); 

    foreach (DataRow row in dt.Rows) 
    {
        T entity = Activator.CreateInstance<T>();
        foreach (PropertyInfo p in per)
        {
           object obj = Convert.ChangeType(row[p.Name], p.PropertyType); 
           p.SetValue(entity, obj);
        }
        list.Add(entity);
    }

    return list;
}      

猛地一看是不是有點哇塞~,很酷的感覺。

來看看這個反射是個什麼東西吧,按照我的了解+書上的指引來大體粗略的寫一下反射

反射

大多數程式都要處理資料,包括度,寫,操作和顯式資料。

然而,對于某些程式來說,他們操作的不是數字,文本或圖形,而是程式和程式類型本身的資訊。

有關程式及其類型的資料被稱為中繼資料(matadata),他們儲存在程式的程式集中(.dll)。

程式在運作時,可以檢視其它程式及或其本身的中繼資料。一個運作的程式檢視本身的中繼資料或其它程式的中繼資料的行為叫做"反射"。

反射命名空間:System.Reflection

Type類

BCL(基類庫)聲明了一個叫做Type的抽象類,他被設計用來包含類型的特性。使用這個類能讓我們擷取程式使用的類型的資訊。

由于Type是抽象類,是以他不能有執行個體。而是在運作時,CLR(公共語言運作庫)從Type(RunTimeType)派生的類的執行個體,Type包含了類型的資訊。

當我們要通路這些執行個體時,CLR不會傳回派生類的引用而是Type基類的引用,

需要了解的Type重要事項:

1.對于程式中用到的每一個類型,CLR都會建立一個包含這個類型的Type類型的對象。

2.程式中用到的每一個類型都會關聯到獨立的Type類的對象。

3.不管建立的類有多少個執行個體,隻有一個Type對象會關聯到所有的這些執行個體。

如圖:一個運作的程式,他有兩個MyClass對象和一個OtherClass對象。注意:盡管有兩個MyClass的執行個體,隻會有一個Type對象來表示他。

入門反射(一)反射Type類擷取Type對象總結

我們可以從Type對象中擷取需要了解的有關類型的幾乎所有資訊。

列一下常用的成員吧。

System.Type類部分的成員。

入門反射(一)反射Type類擷取Type對象總結

擷取Type對象

object類包含了一個叫做GetType的方法,他傳回對執行個體的Type對象的引用。

由于每一個類型最終都是從object繼承的,是以我麼可以在任何類型對象上使用GetType方法來擷取他的Type對象。

Type type = "任何對象".GetType();      

下面示範一下一個基類跟派生子類。在foreach循環中輸出類的名字以及公用字段的名字。

基類與派生類:

class BaseClass //基類
{
    public int BaseField = 0;
}

class DerivedClass : BaseClass //派生類
{
    public int DerivedField = 0;
}      

通過反射輸出類資訊:

BaseClass bc = new BaseClass();    //基類
DerivedClass dc = new DerivedClass();//派生類

BaseClass[] bca = new BaseClass[] { bc, dc };

foreach (var v in bca)
{
    Type type = v.GetType();
    Console.WriteLine("Type:{0}",type.Name);//輸出類名稱

    FieldInfo[] fields = type.GetFields();//擷取所有公用字段
    foreach (var f in fields)
         Console.WriteLine("Field:{0}",f.Name);//輸出公用字段名稱
}      

輸出結果為:

入門反射(一)反射Type類擷取Type對象總結

類名與公用屬性全部被輸出了。

我們還可以通過typeof運算符來擷取Type對象。

隻需提供類型名作為操作數,他就會傳回Type對象的引用(通常都會用在泛型方法中),如代碼所示。

Type type = typeof(BaseClass);      

總結

反射我隻是初窺門徑,如果有錯誤的地方請各位大佬指正。

反射肯定不會隻輸出這些名字。

反射還可以設定類型裡公用的值。還可以調用類型中公用的方法。

等到下一篇講吧。

繼續閱讀