Type類別
在取得型別之前,得先說明什麼是中繼資料(Metadata)、什麼是反映(Reflection)
中繼資料(Metadata)
描述資料的資料,就是中繼資料!? (蛤?
在CLR中,中繼資料就是描述一個模組的定義或其參考的所有東西。因為CLR程式設計是物件導向的,所以中繼資料描述的東西就是類別和它們的成員,及其伴隨而來的特性、屬性和關聯。中繼資料正是反映(Reflection)機制能夠運作的基礎,中繼資料儲存了類別內部所有資訊,表示程式可以動態地得到整個程式集內部結構。
中繼資料包含:
- 型別名稱
- Assembly區塊
- 建構式
- 屬性
- 方法
- 特性
聽起來很抽象,就讓我們把中繼資料具現化吧!!!
我先建立一個有屬性、建構式跟方法的簡單類別
// 類別名稱
class Program
{
// 屬性
public int Score { get; set; }
// 建構式
public Program(int score)
{
this.Score = score;
}
// 方法
public string GetHelloString()
{
return "Hello";
}
static void Main(string[] args)
{
Console.WriteLine("Hey");
Console.Read();
}
}
Release編譯後,利用反組譯工具ILDasm.exe工具檢查中繼資料
可以很清楚看到Program類別底下
- 有一個傳入int32的.ctor建構式
- 回傳string() GetHelloString方法
- 無回傳值Main方法
- 屬性 get_Score,set_Score
程式集的所有內部資訊都在中繼資料一覽無遺,並且中繼資料的資料結構是標準固定的,這使得外部程式碼可以動態地獲取程式集的資訊並加以使用,這也完成了.NET最獨特的一個特性:反映
反映(Reflection)
反映提供一種動態分析、建立和呼叫的機制。在.NET框架中,一個系統可以由多個程式集組成,一個程式集可能包含很多模組,而一個模組中會有很多型別,每個型別可以包含欄位的和方法,方法又可以包含輸入參數和輸出參數等多種資料,在.NET中反映機制可以動態地分析程式集,並且使用程式集中的類別和方法。
取得型別(Type)
在使用反映之前,要先知道如何取得型別,以下將介紹幾個取得型別的方式,懂得取得型別後,就可以開始使用反映分析、存取資料。
public class Animal
{
public Animal()
{
this.NumberOfLegs = 4;
}
public Animal(int number)
{
this.NumberOfLegs = number;
}
public int NumberOfLegs { get; set; }
public string SayWoo()
{
return "Woo";
}
}
static void Main(string[] args)
{
var dog = new Animal() { NumberOfLegs = 4 };
// 方法一 編譯時期取得
Type t1 = typeof(Animal);
// 方法二 執行時期取得
Type t2 = dog.GetType();
Console.WriteLine(t2.Name);
// output: Animal
Console.WriteLine(t2.FullName);
// output: HowToGetTypedata.Animal
Console.WriteLine(t2.Assembly);
// output: HowToGetTypedata, Version = 1.0.0.0,
// Culture=neutral, PublicKeyToken=null
}
方法一與方法二結果是一樣的,最大的差別GetType是從類別實例(instance)取得Type,如果你沒有實例(instance),但是知道類別名稱則是使用typeof。
如何動態建立一個型別? 因為上述方法二,是沒有實例的,所以可用動態建立的方式,建立一個實例出來。
方法有兩個
- Activator.CreateInstance
- 使用Type.GetConstructors
// 方法一
var newAnimal = Activator.CreateInstance(typeof(Animal)) as Animal;
// 方法二
// 使用預設建構式
var animalConstructor = typeof(Animal).GetConstructors()[0];
var newAnimal2 = animalConstructor.Invoke(null) as Animal;
存取屬性
var animal = new Animal();
Type type = animal.GetType();
PropertyInfo property = type.GetProperty("NumberOfLegs");
var value = property.GetValue(animal);
Console.WriteLine(value); // output : 4
呼叫方法
var animal = new Animal();
Type type = animal.GetType();
MethodInfo method = type.GetMethod("SayWoo");
var value = method.Invoke(animal, null).ToString();
Console.WriteLine(value); // output : Woo
以上就是Type一些基本運用,下一章節將會詳細介紹反映(Reflection)的應用。
一天一分享,身體好健康。
該追究的不是過去的原因,而是現在的目的。