.NET序列化的一點技巧(附Demo)


閱讀目錄

 

介紹

  序列化是將對象狀態轉換為可保持或傳輸的形式的過程。序列化的補集是反序列化,后者將流轉換為對象。這兩個過程一起保證數據易於存儲和傳輸。

.NET Framework 提供了兩個序列化技術:

  • 二進制序列化保持類型保真,這對於多次調用應用程序時保持對象狀態非常有用。例如,通過將對象序列化到剪貼板,可在不同的應用程序之間共享對象。您可以將對象序列化到流、磁盤、內存和網絡等。遠程處理使用序列化,“按值”在計算機或應用程序域之間傳遞對象。

  • XML 序列化只序列化公共屬性和字段,並且不保持類型保真。當您希望提供或使用數據而不限制使用該數據的應用程序時,這一點非常有用。由於 XML 是開放式的標准,因此它對於通過 Web 共享數據來說是一個理想選擇。SOAP 同樣是開放式的標准,這使它也成為一個理想選擇。

詳細

  具體命名空間:

  包含可用於序列化和反序列化對象的類。(包括System.Runtime.Serialization.Formatters.Binary.BinaryFormatter,還有WCF中用到的DataContractAttribute, DataMemberAttribute

  包含可用於將對象序列化為 XML 格式的文檔或流的類。

  WCF大家很熟悉,一般的書籍都對基礎的東西有很多內容的講解,這里就對非WCF的一些序列化技巧拋個磚。

一:序列化標記

  需要序列化:[Serializable]也可以寫成[SerializableAttribute]

特性“Serializable”只在“class, struct, enum, delegate”聲明中有效。所以只能在類,結構體等上面標記。

  不需要序列化:[NonSerialized]也可以寫成[NonSerializedAttribute]

特性“NonSerialized”只在“field”聲明中有效。所以只能在字段上標記,連屬性器都不行。

二:特殊情況:

  事件的標記:

[field: NonSerializedAttribute()],需要加入field標記。

  屬性的標記:

其實我們叫的屬性是屬性器,是一對Get,Set方法。既然是方法,當然不是字段了,所以是不能序列化標記或者排除的,那我們怎么去處理某些屬性不需要序列化的情況列。方法也是有的,需要把屬性器中的Get,Set方法寫實,即該有的字段還是得定義,不能偷懶,然后在該有的字段上面標記為不需要序列化。

三:序列化的特殊用法

  學過C#的時候,大家都知道了個值類型,引用類型的概念,也可能知道了ICloneable這個接口,這個克隆接口可以復制對象,如實例化個student,然后調用Clone()即可以得到該對線的淺層副本

  淺層克隆就是只把改對象的值類型和引用類型的地址復制了,但是,原來對象中的被引用類型的對象發生改變,比如:student類中有個classroom,classroom中的某個字段發生改變,這樣克隆后的對線的classroom的值也是會變的。除非classroom這個類也實現ICloneable接口。

  序列化克隆的好處就是不用考慮淺層復制,深層復制,直接將要克隆的對象序列化,然后反序列化得到的對象就是我們期望的結果。

處理

  按照上面的說明,代碼如下:

Student類

 1     [Serializable]
 2     public class Student
 3     {
 4         [field: NonSerializedAttribute()]
 5         public event EventHandler Changed;
 6         [NonSerialized]
 7         private ExParam param;
 8 
 9         public string ID
10         {
11             get;
12             set;
13         }
14 
15         public string Name
16         {
17             get;
18             set;
19         }
20 
21         public ClassRoom Room
22         {
23             get;
24             set;
25         }
26 
27         public ExParam Param
28         {
29             get
30             {
31                 return param;
32             }
33             set
34             {
35                 param = value;
36             }
37         }
38     }

ClassRoom類

 1     [Serializable]
 2     public class ClassRoom
 3     {
 4 
 5         public string Name
 6         {
 7             get;
 8             set;
 9         }
10 
11         public string Address
12         {
13             get;
14             set;
15         }
16     }

ExParam類

1     public class ExParam
2     {
3         public string Name
4         {
5             get;
6             set;
7         }
8     }

Util類

 1     public class Util
 2     {
 3         public static byte[] SerializeObject(object obj)
 4         {
 5             if (obj == null)
 6                 return null;
 7 
 8             using (MemoryStream memory = new MemoryStream())
 9             {
10                 BinaryFormatter formatter = new BinaryFormatter();
11                 formatter.Serialize(memory, obj);
12                 memory.Position = 0;
13                 byte[] read = new byte[memory.Length];
14                 memory.Read(read, 0, read.Length);
15                 memory.Close();
16                 return read;
17             }
18         }
19 
20 
21         public static object DeserializeObject(byte[] data)
22         {
23             object obj = null;
24             if (data == null)
25                 return obj;
26 
27             using (MemoryStream memory = new MemoryStream(data))
28             {
29                 memory.Position = 0;
30                 BinaryFormatter formatter = new BinaryFormatter();
31                 obj = formatter.Deserialize(memory);
32                 memory.Close();
33                 return obj;
34             }
35         }
36     }

主窗體

 1  private void Form1_Load(object sender, EventArgs e)
 2         {
 3             Student student = new Student()
 4             {
 5                 ID = "201401",
 6                 Name = "攻城獅",
 7                 Room = new ClassRoom()
 8                 {
 9                     Name = "博客園",
10                     Address = "小山村"
11                 },
12                 Param = new ExParam()
13                 {
14                     Name = "程序猿"
15                 }
16             };
17 
18             byte[] data = Util.SerializeObject(student);
19 
20             Student student1 = Util.DeserializeObject(data) as Student;
21 
22             Print(student);
23             Print(student1);
24         }
25 
26         private void Print(Student student)
27         {
28             string info =string.Format("{0}{1}{2}{3}"
29                          , "hashcode:" + student.GetHashCode().ToString() + " "
30                          , student.ID + " " + student.Name + " "
31                          , student.Room != null ? student.Room.Name + " " + student.Room.Address + " "+student.Room.GetHashCode().ToString()+" " : "room is null "
32                          , student.Param != null ? student.Param.Name : "param is null"
33                          );
34             listPrint.Items.Add(info);
35         }


結論

  上述代碼輸出:

   

從上述代碼輸出的結果我們可以看出

  • student是被序列化的,student1是用student的序列化的二進制反序列化出來的,兩個的hashcode不一樣,所以是兩個對象。
  • 標記了序列化的字段都被序列化了,沒標記的序列化字段Param是空的。
  • student中的屬性Room是引用類型,標記為序列化,student和student1的Room里的值內容一樣但是hashcode不一樣,所以這Room也是我們期望的兩個對象。

 

Demo下載

源碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM