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

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

2013-11-13 12:22:40  來源: .NET編程 


  如果事先完全了解需要轉換的正式數據類型(例如自己編寫代碼時)事情就變得非常簡單

foreach(Address a in AddressList)
{
 ConsoleWriteLine(Address:{} aID);
 ConsoleWriteLine(\tStreet:{} aStreet);
  // and so on
}

  然而如果預先不知道在運行時會遇到的數據類型情況會變得十分有趣您如何編寫象這樣的一般框架代碼?

  MyFrameworkTranslateObject(object input MyOutputWriter output)

  首先您需要決定哪些類型成員對序列化有用可能的情況包括僅捕獲特定類型的成員例如基元系統類型或提供一種機制以供類型作者說明哪些成員需要被序列化例如在類型成員上使用自定義屬性作為標記)您僅可以捕獲特定類型的成員例如基元系統類型或類型作者能夠說明哪些成員需要被序列化(可能的方法是在類型成員上使用自定義屬性作為標記)

  一旦記錄清楚需要轉換的數據結構成員您接著需要做的是編寫邏輯從傳入的對象枚舉和檢索它們反射在這裡擔負了繁重的任務讓您既可以查詢數據結構又可以查詢數據值

  出於簡單性考慮我們來設計一個輕型轉換引擎得到一個對象獲取所有其公共屬性值通過直接調用 ToString 將它們轉換成字符串然後將這些值序列化對於一個名為input的給定對象算法大致如下

  調用 inputGetType 以檢索 SystemType 實例該實例描述了 input 的底層結構

  用 TypeGetProperties 和適當的 BindingFlags 參數將公共屬性作為 PropertyInfo 實例檢索

  使用 PropertyInfoName 和 PropertyInfoGetValue將屬性作為鍵值對檢索

  在每個值上調用 ObjectToString 將其(通過基本方式)轉化為字符串格式

  將對象類型的名稱和屬性名稱字符串值的集合打包成正確的序列化格式

  這一算法明顯簡化了事情同時也抓住了得到運行時數據結構並將其轉化為自描述型數據的要旨但這裡有一個問題性能之前提到反射對於類型處理和值檢索的成本都很高本示例中我在每個提供類型的實例中執行了完整的類型分析

  如果以某種方式可以捕獲或保留您對於類型結構的理解以便日後不費力地檢索它並有效處理該類型的新實例;換句話說就是往前跳到示例算法中的步驟 #?好消息是利用 NET Framework 中的功能完全可能做到這一點一旦您理解了類型的數據結構便可以使用 CodeDom 動態生成綁定到該數據結構的代碼您可以生成一個幫助器程序集其中包含幫助器類和引用了傳入類型並直接訪問其屬性的方法(類似托管代碼中的任何其他屬性)因此類型檢查只會對性能產生一次影響

  現在我將修正這一算法新類型

  獲得對應於該類型的 SystemType 實例

  使用各種 SystemType 訪問器檢索架構(或至少檢索對序列化有用的架構子集)例如屬性名稱字段名稱等

  使用架構信息生成幫助器程序集(通過 CodeDom)該程序集與新類型相鏈接並有效地處理實例

  在幫助器程序集中使用代碼提取實例數據

  根據需要序列化數據

  對於給定類型的所有傳入數據可以往前跳到步驟 #較之顯式檢查每一實例這麼做可以獲得巨大的性能提升

  我開發了一個名為 SimpleSerialization 的基本序列化庫它用反射和 CodeDom(本專欄中可下載)實現了這一算法主要組件是一個名為 SimpleSerializer 的類是用戶用一個 SystemType 實例構造所得在構造函數中新的 SimpleSerializer 實例會分析給定的類型利用幫助器類生成一個臨時程序集該幫助器類會緊密綁定到給定的數據類型而且對實例的處理方式就象自己在完全事先了解類型的情況下編寫代碼那樣

  SimpleSerializer 類有如下布局

class SimpleSerializer
{
 public class SimpleSerializer(Type dataType);
 public void Serialize(object input SimpleDataWriter writer);
}

  簡單地令人驚歎!構造函數承擔了最繁重的任務它使用反射來分析類型結構然後用 CodeDom 生成幫助器程序集SimpleDataWriter 類只是用來闡明常見序列化模式的數據接收器

  要序列化一個簡單的 Address 類實例用下面的偽代碼即可完成任務

  SimpleSerializer mySerializer = new SimpleSerializer(typeof(Address));

  SimpleDataWriter writer = new SimpleDataWriter();

  mySerializerSerialize(addressInstance writer);

  結束

  強烈建議您親自試用一下示例代碼尤其是 SimpleSerialization 庫我在 SimpleSerializer 一些有趣的部分都添加了注釋希望能夠有所幫助當然如果您需要在產品代碼中進行嚴格的序列化那麼確實要依靠 NET Framework 中提供的技術(例如 XmlSerializer)但如果您發現在運行時需要使用任意類型並能高效處理它們我希望您采用我的 SimpleSerialization 庫作為自己的方案

[]  []  []  []  


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