反射這個詞聽起來就很牛逼是吧? 嗯的確,反射是比較高級的特性,只有語言基礎很扎實的Dev們才應該使用它。 搞點反射,可以提高程式的靈活性、可擴展性、耦合度。 反射這東西,是為了動態地運行時載入,相比於靜態代碼。編譯的時候就是板上釘釘了。 就是說,如果你的程式需要在運行時搞一些晚綁定,動態載入或檢查對 ...
反射這個詞聽起來就很牛逼是吧?
嗯的確,反射是比較高級的特性,只有語言基礎很扎實的Dev們才應該使用它。
搞點反射,可以提高程式的靈活性、可擴展性、耦合度。
反射這東西,是為了動態地運行時載入,相比於靜態代碼。編譯的時候就是板上釘釘了。
就是說,如果你的程式需要在運行時搞一些晚綁定,動態載入或檢查對象之類的操作時,那麼反射歡迎你。
說到這,也許有人立刻就去找反射相關的文檔和教程,想趕緊把反射技術實踐到程式上。
給爺爪巴
使用反射是要分場合的
反射基本上是一種解釋操作,用於欄位啊方法啊接入時要遠慢於直接擼代碼。
因此反射機制主要應用在對靈活性和拓展性要求很高的東西上,普通程式不建議使用。
還有一件事,如果你程式全用的反射。一時反射一時爽,後期維護秒跑路。
程式員最煩的2件事是什麼,維護沒有註釋的代碼和寫註釋。但當程式員看到代碼有一大堆的反射而且沒寫註釋的時候,他們會直接/kill @p就完事了。
因為 反 射 繞 過 了 源 代 碼 的 技 術 ,反射代碼賊JB複雜,相比普通的來說
BCL聲明瞭一個Type類型(它是抽象類),用來包含類型的特性。使用這個類的對象能讓我們獲取程式使用的類型的信息。
由於Type是抽象類,所以它不能被實例化。而是在運行時,CLR創建從Type(RuntimeType)派生的類型的實例。當我們要訪問這些實例的時候,CLR不會返回派生類的引用而是返回Type基類的引用。
關於Type有如下重要的點:
①對於程式每一個需要用到的類型,CLR會穿件一個包含這個類型信息的Type類型的對象(真實的是上面說的派生的類型的實例)。
②程式中用到的每一個類型都會關聯到獨立的Type類的對兩個象。
③無論創建的類型有多少個實例,只有一個Type對象會關聯到所有這些實例。就像下麵的圖表示的一樣。創建了一個OtherClass的實例oc、以及兩個MyClass的實例mc1和mc2,但是在堆上都只會有一個Type對象來的對應他們,如下麵的圖示:
現在我們知道,object類型包含了一個GetType方法,它可以用來返回事例的Type對象引用。由於所有的類都是繼承自object類型,所以所有的類都可以調用GetType來獲得Type類型對象的引用。
所以下麵的代碼,在遍歷派生類的Field的時候才能,把基類的也輸出出來。
//雞肋 class BaseClass { public int BaseField = 0; } //派生類 class DerivedClass : BaseClass { public int DerivedField = 0; } class Program { static void Main(string[] args) { var bc = new BaseClass(); var dc = new DerivedClass(); BaseClass[] bca = new BaseClass[] { bc, dc }; foreach(var v in bca) { //獲取類型 Type t = v.GetType(); Console.WriteLine("Object Type: {0}", t.Name); //獲取類中的欄位 FieldInfo[] fi = t.GetFields(); foreach (var f in fi) Console.WriteLine(" Field:{0}", f.Name); Console.WriteLine(); } Console.WriteLine("End!"); Console.ReadKey(); } }
方法二:通過typeof()方法來獲取一個類型的Type對象引用。例如下麵的代碼:
1 |
Type t = typeof (DerivedClass);
|
//通過程式集獲取類型 var baseType = Assembly.GetExecutingAssembly().GetType("TestDemo.BaseClass"); var derivedType = Assembly.GetExecutingAssembly().GetType("TestDemo.DerivedClass");
很好,來個常用的騷操作。結合GetType和typeof操作,可以做很多事情....
static void Main(string[] args) { var intArray = typeof(int).MakeArrayType(); var int3Array = typeof(int).MakeArrayType(3); Console.WriteLine($"是否是int 數組 intArray == typeof(int[]) :{intArray == typeof(int[]) }"); Console.WriteLine($"是否是int 3維數組 intArray3 == typeof(int[]) :{int3Array == typeof(int[]) }"); Console.WriteLine($"是否是int 3維數組 intArray3 == typeof(int[,,]):{int3Array == typeof(int[,,]) }"); //數組元素的類型 Type elementType = intArray.GetElementType(); Type elementType2 = int3Array.GetElementType(); Console.WriteLine($"{intArray}類型元素類型:{elementType }"); Console.WriteLine($"{int3Array}類型元素類型:{elementType2 }"); //獲取數組的維數 var rank = int3Array.GetArrayRank(); Console.WriteLine($"{int3Array}類型維數:{rank }"); Console.ReadKey(); }
未完待續...
所以下麵的代碼,在遍歷派生類的Field的時候才能,把基類的也輸出出來。