不同命名空间的对象二进制反序列化问题
本質上說,這并不是二進制序列化的問題,甚至不關序列化的問題。
你想要的是在兩個內部結構一致但在不同命名空間(甚至不同項目)的同名類間做類型轉換。
?
這個問題很常見,因為實際工作中經常會有此類需求,但是我們又不可能手動的把每個字段的值都抄來抄去。
?
解決此問題的方法很多,但都逃不開一個關鍵思想:A不知道B的存在,B不知道A的存在,那么我就找出一個C,只要A和B都能以C的形式表示,那么轉換就不是問題。這里的C是概念上的一個標準,用于當做A和B轉換的橋梁。
?
普遍的解決方法:
-
如一樓所說,XmlSerializer序列化器能夠將一個可Xml序列化的類A的“內容”部分抽取出來序列化成Xml片段,也能夠將其反序列化為一個符合該Xml“格式”的類B。代碼如下。
序列化端:
| 1 2 3 4 5 6 7 8 | System.Xml.Serialization.XmlSerializer?xs?=?new?System.Xml.Serialization.XmlSerializer(typeof(classA)); System.IO.Stream?stream?=?new?System.IO.FileStream(@"c:\tmp.txt",System.IO.FileMode.OpenOrCreate); xs.Serialize(stream,?new?classA?{?i?=?10,?s?=?"hello"?}); stream.Dispose(); 反序列化端: ?System.Xml.Serialization.XmlSerializer?xsb?=?new?System.Xml.Serialization.XmlSerializer(typeof(classA)); ?classA?b?=?(classA)xsb.Deserialize(new?System.IO.FileStream(@"c:\tmp.txt",?System.IO.FileMode.Open,?System.IO.FileAccess.Read)); |
打開c:\tmp.txt,我們可以看到中間傳輸的內容是
| 1 2 3 4 5 | <?xml?version="1.0"?> <classA?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?xmlns:xsd="http://www.w3.org/2001/XMLSchema"> ??<i>10</i> ??<s>hello</s> </classA> |
這表明了傳輸的內容只關注類名和共有屬性/字段。所以在反序列化端,只要我們有同樣結構的同名類classA,是可以直接從Xml流進行轉換的。當然使用內存流、字節流等都是可以的。這里一定要切記三點:同名同結構(指共有字段/屬性部分)的兩個類,以及只能序列化公有字段和屬性,兩個類都必須有默認構造方法。
?
Xml序列化的優點在于只序列化必要部分且消耗較少,常用于序列化DataTable等結構。
?
2.第二種方法是使用接口。也許你的兩個類分處不同的命名空間或者不同項目,但是只要都能訪問到同一interface,那么我們可以稍微費點功夫寫一個兩個都“認識”的接口,通過接口來轉換對象。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public?interface?dataInterface ????{ ????????int?i{get;set;} ????????string?s{get;set;} ????} ????[Serializable] ????public?class?classA?:?dataInterface ????{ ????????public?int?i{get;set;} ????????public?string?s{get;set;} ????} ????[Serializable] ????public?class?classB?:?dataInterface ????{ ????????public?int?i{get;set} ????????public?string?s{get;set;} ????} |
如此,不管classA和classB在哪里,只要你認得dataInterface,那么就可以用其來傳輸、訪問和轉換。傳輸的過程相比xml序列化就靈活多了,你可以使用socket、文件、消息、甚至共享內存等等手段來傳輸,序列化也可以使用萬能的二進制序列化,因為你傳出和接受的,都是dataInterface對象而已。
?
序列化端(二進制序列化+文件傳輸舉例):
| 1 2 3 4 | ?System.Runtime.Serialization.Formatters.Binary.BinaryFormatter?formatter?=?new?System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); ????????????System.IO.FileStream?fs?=?new?System.IO.FileStream(@"c:\tmp",?System.IO.FileMode.OpenOrCreate,?System.IO.FileAccess.Write); ????????????formatter.Serialize(fs,?(new?classA?{?i?=?10,?s?=?"hello"?})); ????????????fs.Dispose(); |
反序列化:
?
| 1 | dataInterface?data?=?(dataInterface)formatter.Deserialize(new?System.IO.FileStream(@"c:\tmp",?System.IO.FileMode.OpenOrCreate,?System.IO.FileAccess.Read)); |
此方法優缺點顯而易見。優點是無視兩個類的位置、無需同名同結構,缺點是有額外工作(寫接口)外加反序列化后只能得到接口不能得到classB。額外注意,上例中使用的二進制序列化需要在類上標記[Serializable]。
?
?
除此之外還有很多種方法可以做跨域類型轉換,但并不常用,這里就不再敖述了。
轉載于:https://www.cnblogs.com/yy1234/p/8405556.html
總結
以上是生活随笔為你收集整理的不同命名空间的对象二进制反序列化问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再说说作用域
- 下一篇: Uva 10048 - Audiopho