熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

對.NET Framework 反射的反思[3]

2022-06-13   來源: .NET編程 

  動態調用代碼

  迄今為止我已經獲得運行時對象的句柄(如類型和方法)僅作描述用例如輸出它們的名稱但是如何做得更多呢?如何實際調用某個方法呢?

  此例的幾個要點是首先從一個 MyClass mc 實例檢索一個 SystemType 實例然後從該類型檢索一個 MethodInfo 實例最後當調用 MethodInfo 時通過把它作為調用的第一個參數來傳遞將其綁定到另一個 MyClass (mc) 實例中

  前面講過對於您預期在源代碼中見到的類型和對象使用之間的區別這個示例使這種區別變得模糊邏輯上您檢索了一個方法的句柄然後調用該方法就象它屬於一個不同的對象一樣對於熟悉函數式編程語言的程序員來說這可能輕而易舉;但對於只熟悉 C# 的程序員來說要分離對象實現和對象實例化可能就不是那麼直觀了

  組合在一起

  至此我已經探討過檢查和調用的基本原理接下來我會用具體的例子把它們組合在一起設想您希望交付一個庫帶有必須處理對象的靜態幫助器函數但在設計的時候您對這些對象的類型沒有任何概念!這要看函數調用方的指示看他希望如何從這些對象中提取有意義的信息函數將接受一個對象集合和一個方法的字符串描述符然後它將遍歷該集合調用每個對象的方法用一些函數聚合返回值

  就此例而言我要聲明一些約束條件首先字符串參數描述的方法(必須由每個對象的底層類型實現)不會接受任何參數並將返回一個整數代碼將遍歷對象集合調用指定的方法逐步計算出所有值的平均值最後因為這不是生產代碼在求和的時候我不用擔心參數驗證或整數溢出

  在浏覽示例代碼時可以看到主函數與靜態幫助器 ComputeAverage 之間的協議除了對象自身的通用基類之外並不依賴任何類型信息換句話說您可以徹底改變正在傳送的對象的類型和結構但只要總是能使用字符串描述一個方法且該方法返回整數ComputeAverage 就可以正常工作!

  需要注意的一個關鍵問題跟隱藏在最後這個例子中的 MethodInfo(一般反射)有關注意在 ComputeAverage 的 foreach 循環中代碼只從集合中的第一個對象中抓取一個 MethodInfo然後綁定用於所有後續對象的調用正如編碼所示它運行良好 — 這是 MethodInfo 緩存的一個簡單例子但此處有一個根本性的局限MethodInfo 實例僅能由其檢索對象同等層級類型的實例調用因為傳入了 IntReturner 和 SonOfIntReturner(繼承自 IntReturner)的實例才能這樣運行

  在示例代碼中已經包含了名為 EnemyOfIntReturner 的類它實現了與其他兩個類相同的基本協議但並沒有共享任何常見共享類型換句話說該接口邏輯上等同但在類型層級上沒有重疊要探討 MethodInfo 在該情形下的使用請嘗試向集合添加其他對象通過new EnemyOfIntReturner()得到一個實例再次運行示例您會遇到一個異常指出 MethodInfo 不能用於調用指定的對象因為它和獲得 MethodInfo 時的原始類型完全無關(即使方法名稱和基本協議是等同的)要使您的代碼達到生產水准您需要做好遇到這一情形的准備

  一個可能的解決方案可以是通過自己分析所有傳入對象的類型保留對其共享的類型層級(如果有)的解釋如果下一對象的類型與任意已知類型層級相異就需要獲取和存儲一個新的 MethodInfo另一解決方案是捕獲 TargetException並重新獲取一個 MethodInfo 實例這裡提到的兩種解決方案都各有其優缺點Joel Pobar 為本雜志 五月期寫過一篇優秀的文章內容關於 MethodInfo 緩沖和我所極力推薦的反射性能

  希望此示例演示的向應用程序或框架中添加反射可以為日後的自定義或可擴展性增加更多的靈活性不可否認較之本機編程語言中的同等邏輯使用反射可能會有些繁瑣如果您感到對您或您的客戶來說向代碼中添加基於反射的後期綁定過於麻煩(畢竟他們需要以某種方式在您的框架中說明他們的類型和代碼)那麼可能僅需要適度的靈活性以取得某種平衡

  序列化的高效類型處理

  至此我們已通過若干示例講述了 NET 反射的基本原理接下來讓我們看一下現實世界中的情形如果您的軟件通過 Web 服務或其他進程外遠程技術與其他系統進行交互那麼您很可能已經遇到序列化問題序列化本質上是將活動的占用內存的對象轉變成適合線上傳輸或磁盤存儲的數據格式

  NET Framework 中的 SystemXmlSerialization 命名空間提供了擁有 XmlSerializer 的強大序列化引擎它可以使用任意托管對象並將其轉換成 XML(日後也可將 XML 數據轉換回類型化的對象實例這一過程稱之為反序列化)XmlSerializer 類是一種強大的企業就緒的軟件片斷如果您在項目中面臨序列化問題它將是您的首選但為了教學目的我們來探討如何實現序列化(或者其他類似的運行時類型處理實例)

  設想情形您正在交付一個框架需要使用任意用戶類型的對象實例並將其轉換成某種智能型數據格式例如假定有一個駐留內存的對象類型為如下所示的 Address

(pseudocode)
class Address
{
 AddressID id;
 String Street City;
 StateType State;
 ZipCodeType ZipCode;
}

  如何生成適當的數據表示形式以方便日後使用?或許一個簡單的文本呈現將解決這一問題

  Address:

  Street: Microsoft Way

  City: Redmond

  State: WA

  Zip:

[]  []  []  []  


From:http://tw.wingwit.com/Article/program/net/201311/15774.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.