如果事先完全了解需要轉換的正式數據類型(例如自己編寫代碼時)
事情就變得非常簡單
foreach(Address a in AddressList)
{
Console
WriteLine(
Address:{
}
a
ID);
Console
WriteLine(
\tStreet:{
}
a
Street);
// and so on
}
然而
如果預先不知道在運行時會遇到的數據類型
情況會變得十分有趣
您如何編寫象這樣的一般框架代碼?
MyFramework
TranslateObject(object input
MyOutputWriter output)
首先
您需要決定哪些類型成員對序列化有用
可能的情況包括僅捕獲特定類型的成員
例如基元系統類型
或提供一種機制以供類型作者說明哪些成員需要被序列化
例如在類型成員上使用自定義屬性作為標記)
您僅可以捕獲特定類型的成員
例如基元系統類型
或類型作者能夠說明哪些成員需要被序列化(可能的方法是在類型成員上使用自定義屬性作為標記)
一旦記錄清楚需要轉換的數據結構成員
您接著需要做的是編寫邏輯
從傳入的對象枚舉和檢索它們
反射在這裡擔負了繁重的任務
讓您既可以查詢數據結構又可以查詢數據值
出於簡單性考慮
我們來設計一個輕型轉換引擎
得到一個對象
獲取所有其公共屬性值
通過直接調用 ToString 將它們轉換成字符串
然後將這些值序列化
對於一個名為
input
的給定對象
算法大致如下
調用 input
GetType 以檢索 System
Type 實例
該實例描述了 input 的底層結構
用 Type
GetProperties 和適當的 BindingFlags 參數
將公共屬性作為 PropertyInfo 實例檢索
使用 PropertyInfo
Name 和 PropertyInfo
GetValue
將屬性作為鍵
值對檢索
在每個值上調用 Object
ToString 將其(通過基本方式)轉化為字符串格式
將對象類型的名稱和屬性名稱
字符串值的集合打包成正確的序列化格式
這一算法明顯簡化了事情
同時也抓住了得到運行時數據結構
並將其轉化為自描述型數據的要旨
但這裡有一個問題
性能
之前提到
反射對於類型處理和值檢索的成本都很高
本示例中
我在每個提供類型的實例中執行了完整的類型分析
如果以某種方式可以捕獲或保留您對於類型結構的理解
以便日後不費力地檢索它
並有效處理該類型的新實例;換句話說
就是往前跳到示例算法中的步驟 #
?好消息是
利用
NET Framework 中的功能
完全可能做到這一點
一旦您理解了類型的數據結構
便可以使用 CodeDom 動態生成綁定到該數據結構的代碼
您可以生成一個幫助器程序集
其中包含幫助器類和引用了傳入類型並直接訪問其屬性的方法(類似托管代碼中的任何其他屬性)
因此類型檢查只會對性能產生一次影響
現在我將修正這一算法
新類型
獲得對應於該類型的 System
Type 實例
使用各種 System
Type 訪問器檢索架構(或至少檢索對序列化有用的架構子集)
例如屬性名稱
字段名稱等
使用架構信息生成幫助器程序集(通過 CodeDom)
該程序集與新類型相鏈接
並有效地處理實例
在幫助器程序集中使用代碼
提取實例數據
根據需要序列化數據
對於給定類型的所有傳入數據
可以往前跳到步驟 #
較之顯式檢查每一實例
這麼做可以獲得巨大的性能提升
我開發了一個名為 SimpleSerialization 的基本序列化庫
它用反射和 CodeDom(本專欄中可下載)實現了這一算法
主要組件是一個名為 SimpleSerializer 的類
是用戶用一個 System
Type 實例構造所得
在構造函數中
新的 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();
mySerializer
Serialize(addressInstance
writer);
結束 強烈建議您親自試用一下示例代碼
尤其是 SimpleSerialization 庫
我在 SimpleSerializer 一些有趣的部分都添加了注釋
希望能夠有所幫助
當然
如果您需要在產品代碼中進行嚴格的序列化
那麼確實要依靠
NET Framework 中提供的技術(例如 XmlSerializer)
但如果您發現在運行時需要使用任意類型並能高效處理它們
我希望您采用我的 SimpleSerialization 庫作為自己的方案
[] [] [] []
From:http://tw.wingwit.com/Article/program/net/201311/15773.html