C#中如何理解【反射】技術

你首先要理解一下概念:

 一 類型(Type) 對象是什麼

比如 object x; x是對象,object就是它的類型,在程序中如何描述類型這個概念呢?

就是Type(System.Type)。要獲取某個類的類型可以用typeof()操作符

 

 object a;object b; DataTable t;

 

aType = typeof(object);Type bType = typeof(object);tType = typeof(DataTable);

 

aType==bType!=tType;

 

二 程序集(Assembly) 就是你IDE生成的.exe或.dll文件的運行時就叫程序集。

所有的代碼都在程序集中。你可以通過Assembly.Load()系列函數動態加載程序集(這一步是動態+載代碼的前提,因爲所有的代碼都在程序集中)。

 

 三 動態加載

我們普通調用代碼是: 對象名.方法名(參數列表);

class a

{    void func(int x)

      {

      }

    public static void Main(string[] args)

     {

         //創建對象 a a1 = new a();

         //調用函數 a1.func(1);

      }

 }

 

用反射動態調用代碼是

//加載程序集 System.Reflection.Assembly asm = Assembly.LoadFile(assemblyPath);

 

//獲取類型 Type aType = asm.GetType("名字空間.類名");

 

//獲取沒有參數的構造函數 System.Reflection.ConstructorInfo conn = t.GetConstructor(new Type[0]);

 

//調用沒有參數的構造函數,Invoke返回object它其是a類 object a1 = conn.Invoke(new object[0]);

 //獲取參數類型爲int,函數名爲func的方法 MethodInfo method = t.GetMethod("func",new Type[]{typeof(int)});

 

//在a1上調用func方法,參數爲1 method.Invoke(a1,new object[]{1});

 動態調用(後一種方法)比靜態調用更復雜,而且效率大概低20倍(網上有個哥們好像測試過)。只有在特殊的時候才調用動態加載動態調用---比如,你的主程序啓動的時候子模塊還沒有,要根據登陸信息下載子模塊代碼並調用子模塊代碼,就只能用動態+載來實現了.

 

四 元數據 .net生成的IL代碼中標明瞭在這個(exe,dll)文件中所有的class(類) method(方法)Attribute(屬性) Property(類屬性)的簽名和調用方法信息,這些信息就叫做元數據。所謂的Reflection反射,就是利用元數據,可以瞭解到某個assembly(基本等同文件)中的class。。。。。 (就是上面那一串咚咚)信息和調用方法。

 

五 .net framework 在.net framework中反射類基本都在System.Reflection中。System.Type是反射的核心類. 與它相關的還有System.Attribute命名空間。

 

 

 

用生活中的例子來講解什麼是反射以及反射的基本使用方式。

 

我先問大家一個問題:“《集結號》中谷子地穿的南朝鮮軍服從哪兒來?”顯然不是臨時找裁縫趕製的,肯定是從俘虜身上扒下來的。好,那我們就來補充一點兒《集結號》的鏡頭看看什麼是反射。

一天傍晚,一名又飢又渴的南朝鮮掉隊士兵在鄉間小路上蹣跚地走着,他甚至都快扛不動身上的槍了,也不知道隊伍在哪裏,只好認準一個方向努力尋找。“不許動!”從路邊草叢中跳出的兩名埋伏着的中國士兵喝道,這名南朝鮮士兵本來就精疲力盡,哪受得了這番驚嚇,當時就一屁股坐在地上了。中國士兵把他押回營部並向上級報告,他們在附近巡邏的時候意外俘獲一名南朝鮮掉隊士兵,聽候處置。

這件事情被上報到王團長那裏,王團長正拿着放大鏡跟幾名軍官在地圖前研究作戰方案,聽到這件事,不緊不慢地跟他身邊的高連長說道:“高誠啊,你去看看,沒啥大問題就送到後方戰俘營去。”“是!”高連長接到命令便轉身出去了。

高連長來到一件狹小的房間,那名南朝鮮士兵正半躺在地上,手裏拿着中國士兵給他的饅頭和水,一口一口地嚼着,看到高連長進來了,眼睛裏流露出緊張和恐懼的神情。高連長簡單介紹了中國方面善待俘虜的政策,便開始審問他——注意,反射開始了!

“哪兒的?”“聯合國軍李承晚系部隊3團2排1班。”

“叫什麼名字?”“思密達。”

“這次執行什麼任務?”“潛入貴軍陣地並指引炮兵進行射擊。”

……

一番軟硬兼施之後,高連長掌握了這個小兵所有的信息,整理好材料去跟王團長彙報去了,而這個小兵被帶到一個小屋子裏繼續啃饅頭去了,身上的行頭也被換了下來,換上了專門爲戰俘準備的棉衣。

高連長一手拿着筆錄材料,一手拎着南朝鮮士兵的全套行頭去見了王團長,彙報之後王團長會心地笑了:“小高啊,不錯,你父親當初把你交給我,我就叫他放心,你是塊好料子,怎麼樣,我沒說錯吧,呵呵,不過你也莫要驕傲,我們不能輕敵,這樣,你帶着這身行頭去找穀子地,叫他換上之後連夜潛入敵方陣地,敵人不是想拿炮彈砸我們嗎,那我們就用他們的方式,先發制人,讓老谷指引我軍炮火明日凌晨發起總攻。”

穀子地換上了這身洋行頭,揣了半條煙就出發了,他潛入敵方陣地後冷靜地掏出敵人的望遠鏡進行了周密地觀察,並通過無線電給後方友軍傳遞射擊參數,成功地引導我軍取得了這次重大勝利。

上面的故事情節描述得有點兒多了,趕緊來看代碼吧,首先,我們得有個倒黴的南朝鮮士兵做引子:

   1: namespace UN
   2: {
   3:     internal class SouthKoreaArmy
   4:     {
   5:         public string Name { get; set; }
   6:  
   7:         public string Search(string destination)
   8:         {
   9:             return "OK, fire!";
  10:         }
  11:     }
  12: }

然後,我們用代碼來實現穀子地所完成的行動:

   1: internal class ChineseArmy
   2: {
   3:     public static void Action(object soldier)
   4:     {
   5:         Type type = soldier.GetType();
   6:         object ziDiGu = Activator.CreateInstance(type);
   7:         MethodInfo methodInfo = type.GetMethod("Search");
   8:  
   9:         Console.WriteLine(methodInfo.Invoke(ziDiGu, new object[] { "Position" }));
  10:     }
  11: }

這段代碼很好理解,第5行我們審問了被俘的南朝鮮士兵並得到了他提供的信息和服裝,然後讓老谷用他的服裝化裝成南朝鮮士兵。第7行,小樣,你不是想偵查我嗎,好,咱就來個以牙還牙,用你的方式來搞定你!接下來,穀子地潛入地方陣地並引導了我軍發起總攻。

這裏展示了反射的一些基本應用,例如獲取類型信息、利用獲取的類型動態生成對象,並動態調用其方法。當然,反射機制能做的事情不僅僅是這幾樣,不過目標都一樣,由程序自己去獲取信息、做出反應。在不用擔心性能開銷的情況下,反射可以使你的程序更加靈活強大!

發佈了7 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章