天天看點

.Net元件程式設計之序列化

 .Net元件程式設計之序列化

自動序列化

Serializable屬性

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<code> </code><code>1     [Serializable]</code>

<code> </code><code>2     </code><code>public</code> <code>class</code> <code>SerializableCase</code>

<code> </code><code>3 </code>

<code> </code><code>4     {</code>

<code> </code><code>5 </code>

<code> </code><code>6         </code><code>public</code> <code>SerializableCase() { }</code>

<code> </code><code>7 </code>

<code> </code><code>8         </code><code>private</code> <code>string</code> <code>_State;</code>

<code> </code><code>9 </code>

<code>10         </code><code>public</code> <code>string</code> <code>State</code>

<code>11 </code>

<code>12         {</code>

<code>13 </code>

<code>14             </code><code>get</code> <code>{ </code><code>return</code> <code>_State; }</code>

<code>15 </code>

<code>16             </code><code>set</code> <code>{ _State = value; }</code>

<code>17 </code>

<code>18         }</code>

<code>19 </code>

<code>20     }</code>

在上面的示例類型上加上Serializable屬性這樣将示例類型标記為可序列化類型.

21

22

23

24

25

<code> </code><code>1     </code><code>public</code> <code>class</code> <code>MySerializableCase</code>

<code> </code><code>2     {</code>

<code> </code><code>3         </code><code>public</code> <code>static</code> <code>void</code> <code>BinaryFormatterSerialize()</code>

<code> </code><code>4         {</code>

<code> </code><code>5             IFormatter formatter = </code><code>new</code> <code>BinaryFormatter();</code>

<code> </code><code>6             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"jin.glory"</code><code>, FileMode.Create, FileAccess.ReadWrite);</code>

<code> </code><code>7             </code><code>using</code> <code>(stream)</code>

<code> </code><code>8             {</code>

<code> </code><code>9                 SerializableCase serCase = </code><code>new</code> <code>SerializableCase();</code>

<code>10                 serCase.State = </code><code>"Test"</code><code>;</code>

<code>11                 formatter.Serialize(stream, serCase);</code>

<code>12             }</code>

<code>13         }</code>

<code>14 </code>

<code>15         </code><code>public</code> <code>static</code> <code>void</code> <code>BinaryFormatterDesSerialize()</code>

<code>16         {</code>

<code>17             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"jin.glory"</code><code>, FileMode.Open, FileAccess.Read);</code>

<code>18             IFormatter formatter = </code><code>new</code> <code>BinaryFormatter();</code>

<code>19             </code><code>using</code> <code>(stream)</code>

<code>20             {</code>

<code>21                 SerializableCase serCase = formatter.Deserialize(stream) </code><code>as</code> <code>SerializableCase;</code>

<code>22                 </code><code>return</code> <code>serCase.State;</code>

<code>23             }</code>

<code>24         }</code>

<code>25     }</code>

BinaryFormattSerialize()方法裡隻是執行個體化SerializableCase類型,然後對State屬性指派,代表一個狀态。調用 MySerializableCase.BinaryFormattSerialize()後.NET把序列化好的檔案流儲存到了jin.glory檔案中.

圖1

.Net元件程式設計之序列化

檔案的名稱和字尾格式都是自己随便定義的。然後再調用反序列化,擷取到之前序列化的對象狀态。

<code>1   </code><code>string</code> <code>state = MySerializableCase.BinaryFormattDesSerialize();</code>

<code>2   Console.WriteLine(state);</code>

圖2

.Net元件程式設計之序列化

SoapFormatter是在命名空間System.Runtime.Serialization.Formatters.Soap下的(在System.Runtime.Serialization.Formatters.Soap.dll中)

<code> </code><code>1 </code><code>public</code> <code>class</code> <code>MySerializableCase</code>

<code> </code><code>3         </code><code>public</code> <code>static</code> <code>void</code> <code>SoapFormatterSerialize()</code>

<code> </code><code>5             IFormatter formatter = </code><code>new</code> <code>SoapFormatter();</code>

<code> </code><code>6             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"Soap.xml"</code><code>, FileMode.Create, FileAccess.ReadWrite);</code>

<code>15         </code><code>public</code> <code>static</code> <code>string</code> <code>SoapFormatterDesSerialize()</code>

<code>17             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"Soap.xml"</code><code>, FileMode.Open, FileAccess.Read);</code>

<code>18             IFormatter formatter = </code><code>new</code> <code>SoapFormatter();</code>

和上面的二進制格式化器使用的方式近乎相同,唯一不同的是,使用Soap格式化器生成的序列化檔案耗時更長,占用空間也比較大,但是它是遵循着SOAP協定的,這在跨平台操作資料間是很有用的,平台隻需要解析重建就能把對象重新的生成出來。

26

27

28

29

30

31

32

<code> </code><code>3     {</code>

<code> </code><code>4         </code><code>public</code> <code>SerializableCase() { }</code>

<code> </code><code>6         </code><code>private</code> <code>string</code> <code>_State;</code>

<code> </code><code>8         </code><code>public</code> <code>string</code> <code>State</code>

<code> </code><code>9         {</code>

<code>10             </code><code>get</code> <code>{ </code><code>return</code> <code>_State; }</code>

<code>11             </code><code>set</code> <code>{ _State = value; }</code>

<code>12         }</code>

<code>14         [NonSerialized]</code>

<code>15         </code><code>private</code> <code>DonotSerializable _DonotSerializable;</code>

<code>16 </code>

<code>17         </code><code>public</code> <code>DonotSerializable DonotSerializable</code>

<code>18         {</code>

<code>19             </code><code>get</code> <code>{ </code><code>return</code> <code>_DonotSerializable; }</code>

<code>20             </code><code>set</code> <code>{ _DonotSerializable = value; }</code>

<code>21         }</code>

<code>22     }</code>

<code>23     </code><code>public</code> <code>class</code> <code>DonotSerializable</code>

<code>24     {</code>

<code>25         </code><code>public</code> <code>DonotSerializable() { }</code>

<code>26 </code>

<code>27         </code><code>public</code> <code>string</code> <code>DonotSerializableData</code>

<code>28         {</code>

<code>29             </code><code>get</code><code>;</code>

<code>30             </code><code>set</code><code>;</code>

<code>31         }</code>

<code>32     }</code>

修改了一下第一段的示例代碼,增加了個屬性,并且設定其字段為NonSerialized,這樣在.NET序列化這個類的執行個體的時候,檢測到了[NonSerialized]的時候就會跳過它,因為有的對象确實是不适合序列化來進行持久化的,不過這樣的做的也會有個問題,就是對象的狀态丢失,就是不可序列化的部分會丢失。看一下下面的代碼:

<code>11                 serCase.DonotSerializable = </code><code>new</code> <code>DonotSerializable();</code>

<code>12                 serCase.DonotSerializable.DonotSerializableData = </code><code>"DonotSerializableData"</code><code>;</code>

<code>13                 formatter.Serialize(stream, serCase);</code>

<code>14             }</code>

<code>15         }</code>

<code>17         </code><code>public</code> <code>static</code> <code>string</code> <code>BinaryFormatterDesSerialize()</code>

<code>19             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"jin.glory"</code><code>, FileMode.Open, FileAccess.Read);</code>

<code>20             IFormatter formatter = </code><code>new</code> <code>BinaryFormatter();</code>

<code>21             </code><code>using</code> <code>(stream)</code>

<code>22             {</code>

<code>23                 SerializableCase serCase = formatter.Deserialize(stream) </code><code>as</code> <code>SerializableCase;</code>

<code>24                 </code><code>return</code> <code>serCase.State+</code><code>"_"</code><code>+serCase.DonotSerializable.DonotSerializableData;</code>

<code>25             }</code>

<code>26         }</code>

<code>27      }</code>

修改了上面的二進制格式器的代碼,調用一下測試代碼我們一起來看下結果:

<code>1 MySerializableCase.BinaryFormatterSerialize();</code>

<code>2 </code><code>string</code> <code>state = MySerializableCase.BinaryFormatterDesSerialize();</code>

<code>3 Console.WriteLine(state);</code>

圖3

.Net元件程式設計之序列化

在反序列化的時候,對象SerializableCase的DonotSerializable屬性丢失了,是以才會報錯。

對于這樣的情況,.NET提供了IDeserializationCallback接口,它裡面隻有一個函數void OnDeserialization(object sender),隻要實作了IDeserializationCallback,并且在OnDeserialization函數裡實作具體的對不可序列化對象的初始化。

<code> </code><code>2     </code><code>public</code> <code>class</code> <code>SerializableCase:IDeserializationCallback</code>

<code>22 </code>

<code>23         </code><code>public</code> <code>void</code> <code>OnDeserialization(</code><code>object</code> <code>sender)</code>

<code>24         {</code>

<code>25             _DonotSerializable = </code><code>new</code> <code>DonotSerializable();</code>

<code>26             _DonotSerializable.DonotSerializableData = </code><code>"DonotSerializableData-&gt;Test"</code><code>;</code>

<code>27         }</code>

<code>28     }</code>

按照上面的調用方式,來看一下結果:

圖4

.Net元件程式設計之序列化

這樣是在反序列化的時候,如果檢測到了執行個體類型實作了IDeserializationCallback接口,是在反序列化完成的時候會執行實作了IDeserializationCallback的OnDeserialization()方法,這樣可以對一些不可序列化的屬性狀态在這個方法裡來實作。

.NET2.0 

引進了對序列化事件的支援,當序列化和反序列化的時候,.NET在你的類上調用指定的方法,.NET中定義了四個序列化和反序列化事件。

serializing事件是在序列化發生之前被觸發,

serialized 事件是在序列化之後被觸發,

deserializing事件是在反序列化之前被觸發,

deserialized事件是在反序列化之後被觸發。

引用先前的示例代碼SerializableCase類的初始代碼:

<code>    </code><code>[Serializable]</code>

<code>    </code><code>public</code> <code>class</code> <code>SerializableCase </code><code>//:IDeserializationCallback</code>

<code>    </code><code>{</code>

<code>        </code><code>public</code> <code>SerializableCase() { }</code>

<code>        </code><code>private</code> <code>string</code> <code>_State;</code>

<code>        </code><code>public</code> <code>string</code> <code>State</code>

<code>        </code><code>{</code>

<code>            </code><code>get</code> <code>{ </code><code>return</code> <code>_State; }</code>

<code>            </code><code>set</code> <code>{ _State = value; }</code>

<code>        </code><code>}</code>

<code>    </code><code>}</code>

添加了事件後的示例代碼是這樣的:

33

34

35

36

37

38

39

<code> </code><code>2     </code><code>public</code> <code>class</code> <code>SerializableCase </code>

<code> </code><code>5         </code><code>private</code> <code>string</code> <code>_State;</code>

<code> </code><code>6         </code><code>public</code> <code>string</code> <code>State</code>

<code> </code><code>7         {</code>

<code> </code><code>8             </code><code>get</code> <code>{ </code><code>return</code> <code>_State; }</code>

<code> </code><code>9             </code><code>set</code> <code>{ _State = value; }</code>

<code>10         }</code>

<code>12         [OnSerializing]</code>

<code>13         </code><code>private</code> <code>void</code> <code>OnSerializing(StreamingContext context)</code>

<code>14         {</code>

<code>15             _State = </code><code>"此時的狀态是:序列化之前"</code><code>;</code>

<code>16             Console.WriteLine(State);</code>

<code>17         }</code>

<code>18 </code>

<code>19         [OnSerialized]</code>

<code>20         </code><code>private</code> <code>void</code> <code>OnSerialized(StreamingContext context)</code>

<code>21         {</code>

<code>22             _State = </code><code>"此時的狀态是:序列化之後"</code><code>;</code>

<code>23             Console.WriteLine(State);</code>

<code>25 </code>

<code>26         [OnDeserializing]</code>

<code>27         </code><code>private</code> <code>void</code> <code>OnDeserializing(StreamingContext context)</code>

<code>29             _State = </code><code>"此時的狀态是:反序列化之前"</code><code>;</code>

<code>30             Console.WriteLine(State);</code>

<code>32 </code>

<code>33         [OnDeserialized]</code>

<code>34         </code><code>private</code> <code>void</code> <code>OnDeserialized(StreamingContext context)</code>

<code>35         {</code>

<code>36             _State = </code><code>"此時的狀态是:反序列化之後"</code><code>;</code>

<code>37             Console.WriteLine(State);</code>

<code>38         }</code>

<code>39     }</code>

使用之前定義好的MySerializableCase類型中的靜态方法,稍作修改來示範一下,

<code> </code><code>1         </code><code>public</code> <code>static</code> <code>void</code> <code>SoapFormatterSerialize()</code>

<code> </code><code>2         {</code>

<code> </code><code>3             IFormatter formatter = </code><code>new</code> <code>SoapFormatter();</code>

<code> </code><code>4             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"Soap.xml"</code><code>, FileMode.Create, FileAccess.ReadWrite);</code>

<code> </code><code>5             </code><code>using</code> <code>(stream)</code>

<code> </code><code>6             {</code>

<code> </code><code>7                 SerializableCase serCase = </code><code>new</code> <code>SerializableCase();</code>

<code> </code><code>8                 formatter.Serialize(stream, serCase);</code>

<code> </code><code>9             }</code>

<code>11         </code><code>public</code> <code>static</code> <code>string</code> <code>SoapFormatterDesSerialize()</code>

<code>13             Stream stream = </code><code>new</code> <code>FileStream(</code><code>"Soap.xml"</code><code>, FileMode.Open, FileAccess.Read);</code>

<code>14             IFormatter formatter = </code><code>new</code> <code>SoapFormatter();</code>

<code>15             </code><code>using</code> <code>(stream)</code>

<code>16             {</code>

<code>17                 SerializableCase serCase = formatter.Deserialize(stream) </code><code>as</code> <code>SerializableCase;</code>

<code>18                 </code><code>return</code> <code>serCase.State;</code>

<code>19             }</code>

<code>20             </code>

測試代碼:

<code>1 MySerializableCase.SoapFormatterSerialize();</code>

<code>2 MySerializableCase.SoapFormatterDesSerialize();</code>

<code>3 Console.ReadLine();</code>

圖5

.Net元件程式設計之序列化

從結果中就很明顯的顯示出來了,這裡要說幾句題外話,細心的朋友可能發現了,在SerializableCase類型中的四個事件函數簽名都是相同的,這是因為在.NET中為這個這個序列化和反序列化事件定義的委托就是這個簽名,在這個類型執行個體序列化和反序列化的時候會檢測到.NET會反射執行個體内部所有的函數 檢測是否有附加了序列化事件,如果判斷了有則會繼續檢查這個函數的簽名,如果函數簽名也比對了,就會把這個函數挂上委托。

可以這樣指定一個函數為事件指定調用函數:

<code>1 [OnSerializing]</code>

<code>2 [OnSerialized]</code>

<code>3 [OnDeserializing]</code>

<code>4 [OnDeserialized]</code>

<code>5 </code><code>private</code> <code>void</code> <code>OnGenericSerializEventMethod(StreamingContext context)</code>

<code>6 {</code>

<code>7     ……</code>

<code>8 }</code>

本篇幅序列化内容結束。

     本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1421957,如需轉載請自行聯系原作者

繼續閱讀