如何理解.Net組件程序設計中的序列化,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

.Net組件程序設計之序列化
自動序列化
Serializable屬性
1 [Serializable]
2 public class SerializableCase
3
4 {
5
6 public SerializableCase() { }
7
8 private string _State;
9
10 public string State
11
12 {
13
14 get { return _State; }
15
16 set { _State = value; }
17
18 }
19
20 }在上面的示例類型上加上Serializable屬性這樣將示例類型標記為可序列化類型.
1 public class MySerializableCase
2 {
3 public static void BinaryFormatterSerialize()
4 {
5 IFormatter formatter = new BinaryFormatter();
6 Stream stream = new FileStream("jin.glory", FileMode.Create, FileAccess.ReadWrite);
7 using (stream)
8 {
9 SerializableCase serCase = new SerializableCase();
10 serCase.State = "Test";
11 formatter.Serialize(stream, serCase);
12 }
13 }
14
15 public static void BinaryFormatterDesSerialize()
16 {
17 Stream stream = new FileStream("jin.glory", FileMode.Open, FileAccess.Read);
18 IFormatter formatter = new BinaryFormatter();
19 using (stream)
20 {
21 SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
22 return serCase.State;
23 }
24 }
25 }BinaryFormattSerialize()方法里只是實例化SerializableCase類型,然后對State屬性賦值,代表一個狀態。調用 MySerializableCase.BinaryFormattSerialize()后.NET把序列化好的文件流保存到了jin.glory文件中.
圖1

文件的名稱和后綴格式都是自己隨便定義的。然后再調用反序列化,獲取到之前序列化的對象狀態。
1 string state = MySerializableCase.BinaryFormattDesSerialize(); 2 Console.WriteLine(state);
圖2

SoapFormatter是在命名空間System.Runtime.Serialization.Formatters.Soap下的(在System.Runtime.Serialization.Formatters.Soap.dll中)
1 public class MySerializableCase
2 {
3 public static void SoapFormatterSerialize()
4 {
5 IFormatter formatter = new SoapFormatter();
6 Stream stream = new FileStream("Soap.xml", FileMode.Create, FileAccess.ReadWrite);
7 using (stream)
8 {
9 SerializableCase serCase = new SerializableCase();
10 serCase.State = "Test";
11 formatter.Serialize(stream, serCase);
12 }
13 }
14
15 public static string SoapFormatterDesSerialize()
16 {
17 Stream stream = new FileStream("Soap.xml", FileMode.Open, FileAccess.Read);
18 IFormatter formatter = new SoapFormatter();
19 using (stream)
20 {
21 SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
22 return serCase.State;
23 }
24 }
25 }
和上面的二進制格式化器使用的方式近乎相同,唯一不同的是,使用Soap格式化器生成的序列化文件耗時更長,占用空間也比較大,但是它是遵循著SOAP協議的,這在跨平臺操作數據間是很有用的,平臺只需要解析重建就能把對象重新的生成出來。
1 [Serializable]
2 public class SerializableCase
3 {
4 public SerializableCase() { }
5
6 private string _State;
7
8 public string State
9 {
10 get { return _State; }
11 set { _State = value; }
12 }
13
14 [NonSerialized]
15 private DonotSerializable _DonotSerializable;
16
17 public DonotSerializable DonotSerializable
18 {
19 get { return _DonotSerializable; }
20 set { _DonotSerializable = value; }
21 }
22 }
23 public class DonotSerializable
24 {
25 public DonotSerializable() { }
26
27 public string DonotSerializableData
28 {
29 get;
30 set;
31 }
32 }修改了一下第一段的示例代碼,增加了個屬性,并且設置其字段為NonSerialized,這樣在.NET序列化這個類的實例的時候,檢測到了[NonSerialized]的時候就會跳過它,因為有的對象確實是不適合序列化來進行持久化的,不過這樣的做的也會有個問題,就是對象的狀態丟失,就是不可序列化的部分會丟失??匆幌孪旅娴拇a:
1 public class MySerializableCase
2 {
3 public static void BinaryFormatterSerialize()
4 {
5 IFormatter formatter = new BinaryFormatter();
6 Stream stream = new FileStream("jin.glory", FileMode.Create, FileAccess.ReadWrite);
7 using (stream)
8 {
9 SerializableCase serCase = new SerializableCase();
10 serCase.State = "Test";
11 serCase.DonotSerializable = new DonotSerializable();
12 serCase.DonotSerializable.DonotSerializableData = "DonotSerializableData";
13 formatter.Serialize(stream, serCase);
14 }
15 }
16
17 public static string BinaryFormatterDesSerialize()
18 {
19 Stream stream = new FileStream("jin.glory", FileMode.Open, FileAccess.Read);
20 IFormatter formatter = new BinaryFormatter();
21 using (stream)
22 {
23 SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
24 return serCase.State+"_"+serCase.DonotSerializable.DonotSerializableData;
25 }
26 }
27 }修改了上面的二進制格式器的代碼,調用一下測試代碼我們一起來看下結果:
1 MySerializableCase.BinaryFormatterSerialize(); 2 string state = MySerializableCase.BinaryFormatterDesSerialize(); 3 Console.WriteLine(state);
圖3

在反序列化的時候,對象SerializableCase的DonotSerializable屬性丟失了,所以才會報錯。
對于這樣的情況,.NET提供了IDeserializationCallback接口,它里面只有一個函數void OnDeserialization(object sender),只要實現了IDeserializationCallback,并且在OnDeserialization函數里實現具體的對不可序列化對象的初始化。
1 [Serializable]
2 public class SerializableCase:IDeserializationCallback
3 {
4 public SerializableCase() { }
5
6 private string _State;
7
8 public string State
9 {
10 get { return _State; }
11 set { _State = value; }
12 }
13
14 [NonSerialized]
15 private DonotSerializable _DonotSerializable;
16
17 public DonotSerializable DonotSerializable
18 {
19 get { return _DonotSerializable; }
20 set { _DonotSerializable = value; }
21 }
22
23 public void OnDeserialization(object sender)
24 {
25 _DonotSerializable = new DonotSerializable();
26 _DonotSerializable.DonotSerializableData = "DonotSerializableData->Test";
27 }
28 }按照上面的調用方式,來看一下結果:
圖4

這樣是在反序列化的時候,如果檢測到了實例類型實現了IDeserializationCallback接口,是在反序列化完成的時候會執行實現了IDeserializationCallback的OnDeserialization()方法,這樣可以對一些不可序列化的屬性狀態在這個方法里來實現。
.NET2.0
引進了對序列化事件的支持,當序列化和反序列化的時候,.NET在你的類上調用指定的方法,.NET中定義了四個序列化和反序列化事件。
serializing事件是在序列化發生之前被觸發,
serialized 事件是在序列化之后被觸發,
deserializing事件是在反序列化之前被觸發,
deserialized事件是在反序列化之后被觸發。
引用先前的示例代碼SerializableCase類的初始代碼:
[Serializable]
public class SerializableCase //:IDeserializationCallback
{
public SerializableCase() { }
private string _State;
public string State
{
get { return _State; }
set { _State = value; }
}
}添加了事件后的示例代碼是這樣的:
1 [Serializable]
2 public class SerializableCase
3 {
4 public SerializableCase() { }
5 private string _State;
6 public string State
7 {
8 get { return _State; }
9 set { _State = value; }
10 }
11
12 [OnSerializing]
13 private void OnSerializing(StreamingContext context)
14 {
15 _State = "此時的狀態是:序列化之前";
16 Console.WriteLine(State);
17 }
18
19 [OnSerialized]
20 private void OnSerialized(StreamingContext context)
21 {
22 _State = "此時的狀態是:序列化之后";
23 Console.WriteLine(State);
24 }
25
26 [OnDeserializing]
27 private void OnDeserializing(StreamingContext context)
28 {
29 _State = "此時的狀態是:反序列化之前";
30 Console.WriteLine(State);
31 }
32
33 [OnDeserialized]
34 private void OnDeserialized(StreamingContext context)
35 {
36 _State = "此時的狀態是:反序列化之后";
37 Console.WriteLine(State);
38 }
39 }使用之前定義好的MySerializableCase類型中的靜態方法,稍作修改來演示一下,
1 public static void SoapFormatterSerialize()
2 {
3 IFormatter formatter = new SoapFormatter();
4 Stream stream = new FileStream("Soap.xml", FileMode.Create, FileAccess.ReadWrite);
5 using (stream)
6 {
7 SerializableCase serCase = new SerializableCase();
8 formatter.Serialize(stream, serCase);
9 }
10 }
11 public static string SoapFormatterDesSerialize()
12 {
13 Stream stream = new FileStream("Soap.xml", FileMode.Open, FileAccess.Read);
14 IFormatter formatter = new SoapFormatter();
15 using (stream)
16 {
17 SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
18 return serCase.State;
19 }
20
21 }測試代碼:
1 MySerializableCase.SoapFormatterSerialize(); 2 MySerializableCase.SoapFormatterDesSerialize(); 3 Console.ReadLine();
圖5

從結果中就很明顯的顯示出來了,這里要說幾句題外話,細心的朋友可能發現了,在SerializableCase類型中的四個事件函數簽名都是相同的,這是因為在.NET中為這個這個序列化和反序列化事件定義的委托就是這個簽名,在這個類型實例序列化和反序列化的時候會檢測到.NET會反射實例內部所有的函數 檢測是否有附加了序列化事件,如果判斷了有則會繼續檢查這個函數的簽名,如果函數簽名也匹配了,就會把這個函數掛上委托。
可以這樣指定一個函數為事件指定調用函數:
1 [OnSerializing]
2 [OnSerialized]
3 [OnDeserializing]
4 [OnDeserialized]
5 private void OnGenericSerializEventMethod(StreamingContext context)
6 {
7 ……
8 }看完上述內容,你們掌握如何理解.Net組件程序設計中的序列化的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注創新互聯網站制作公司行業資訊頻道,感謝各位的閱讀!
創新互聯www.cdcxhl.cn,專業提供香港、美國云服務器,動態BGP最優骨干路由自動選擇,持續穩定高效的網絡助力業務部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統配攻擊溯源,準確進行流量調度,確保服務器高可用性。佳節活動現已開啟,新人活動云服務器買多久送多久。
標題名稱:如何理解.Net組件程序設計中的序列化-創新互聯
文章轉載:http://www.yijiale78.com/article26/pgscg.html
成都網站建設公司_創新互聯,為您提供全網營銷推廣、面包屑導航、動態網站、企業建站、微信公眾號、網站制作
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯