2011-02-26 12 views
2

我基本上想創建我自己的二進制序列化類,有點什麼BinaryFormatter類正在做。我如何使用BinaryReaderBinaryWriter類來完成此操作。 我不想要任何代碼,只是一個想法。 謝謝。 PS:請不要告訴我使用BinaryFormatter如何使用BinaryReader和BinaryWriter創建我自己的二進制序列化程序?

+0

如果您沒有說出BinaryFormatter有什麼問題,這是無法準確回答的。 *你的版本需要更好地工作? – 2011-02-26 16:53:48

+0

我正在做這個學習練習。所有的BinaryFormatter都沒有問題+ BinaryFormatter在CF上不受支持,我希望兩種方式都有一個輕量級的格式化程序。 – gigi 2011-02-26 17:01:29

+0

@Hans哦,不要讓我開始:)我可以談談*** ***,整個下午... – 2011-02-26 17:08:45

回答

0

要了解如何實現序列化,你可以看看sharpserializer的c#源代碼。源代碼可以找到here。該代碼也適用於windowsmobile,silverlight。

3

最終,您需要爲每種類型選擇一種策略,然後切換到每種策略; BinaryWriter具有編寫Int32,String等的方法 - 所以一個基本的方法是使用大量的反射和在FieldInfo/PropertyInfo的有效類型的GetTypeCode上開關。我個人認爲避免 BinaryReader/Writer,並直接進入Stream(帶有一個浮動字節[]緩衝區用於工作)。通過使用元編程預編譯每個成員或每種類型的內容,可以減少反射的數量。

其他的事情要考慮:

  • 什麼頭數據,你需要(如果有的話)來標記每個數據字段
  • 你打算怎麼收拾子對象/繼承/列表

兩者都相當容易解決,當然

+0

爲什麼要避免'BinaryReader'和'BinaryWriter'?我用它們(大部分)效果很好。我會不時承認一些煩惱,但總的來說,我更喜歡他們。你認爲使用'byte []'緩衝區的好處是什麼? – 2011-02-26 17:37:57

+0

@Jim - 在我的情況下,數據格式與BinaryReader/Writer會選擇什麼不完全匹配(protobuf使用varint可變長度編碼),並且涉及相當數量的二進制雜耍;也可以直接寫入臨時緩衝區,並儘量減少讀/寫調用的次數。請注意緩衝區滿時被刷新 - 我沒有將整個內存組裝在內存中(這會產生大量的內存開銷)。但主要是第一個原因:它只是不會提供我很多 – 2011-02-26 17:43:23

+0

是的,可變長度編碼對於那些人來說是一種痛苦。謝謝(你的)信息。 – 2011-02-26 18:27:24

0

我會推薦使用類似ProtoBuf .Net的東西,你可以在你的類中使用屬​​性來設置它,它將處理所有的二進制序列化/反序列化。

我最近不得不增加這個功能,以更緊湊的格式在通用類中提供客戶序列化支持。就像Marc提到的,只需要處理序列化/反序列化特定類型的代碼,然後切換到要編寫的特定對象類型的代碼即可。

這裏是一個方法,我把爲了讓一個泛型類內部的數據序列化的基本輪廓:

MemoryStream stream = new MemoryStream(); 
BinaryWriter writer = new BinaryWriter(stream); 

writer.Write(_size); 
for (int i = 0; i < _size; i++) 
    _indices[i].AddToStream(writer); 

if (_serializeDataToStream == null) 
    _serializeDataToStream = (Action<BinaryWriter, int, T[]>)GetTypeSpecificSerializationMethod(); 

_serializeDataToStream(writer, _size, _data); 

return stream.ToArray(); 

這是通用類裏面,_serializeDataToStream是靜態的,所以它只有要查找每種類型一次

private Delegate GetTypeSpecificSerializationMethod() 
{ 
    if (typeof(T) == typeof(double)) 
    { 
     MethodInfo method = this.GetType().GetMethod("SerializeDouble", BindingFlags.Static | BindingFlags.NonPublic); 
     return Delegate.CreateDelegate(typeof(Action<BinaryWriter, int, T[]>), method); 
    } 
    else if (typeof(T) == typeof(ushort)) 
    { 
    ... 


private static void SerializeDouble(BinaryWriter writer, int size, double[] data) 
{ 
    for (int i = 0; i < size; i++) 
    { 
     writer.Write(data[i]); 
    } 
} 
相關問題