[C#] C# 知識回顧 - 序列化

C# 知識回顧 -  序列化

 【博主】反骨仔    【原文地址】http://www.cnblogs.com/liqingwen/p/5902005.htmlhtml

目錄

1、序列化的含義

  序列化 (Serialization)將對象的狀態信息處理爲字節流,以便於存儲或傳輸到內存、數據庫或文件的一個過程。在序列化期間,對象將其當前狀態寫入到臨時或持久性存儲區,主要目的是保存對象的狀態。便於往後從該狀態中進行還原,建立新的對象,這個過程又稱爲反序列化。前端

 

1.1 序列化的工做方式

圖1.1-1數據庫

 
圖:序列化
  對象被序列化爲字節流(包括數據、對象的類型信息:如版本、區域性和程序集名稱) --> 存儲到 DB、IO 等地方。
 

1.2 用於序列化

  咱們在數據交換的時候常進行序列化保存對象的數據信息,在須要使用它的時候再進行反序列化從新讀取對象的信息並進行校驗和存儲的一些工做。經常使用於 Web 間傳遞數據,跨域傳遞,ASP .NET 後臺代碼往前端傳遞數據(js 進行解析處理)。
 

1.3 使對象可序列化

  進行序列化的操做,須要:一個帶序列化的對象,一個是包含序列化對象的流和一個序列化器( Formatter)。
  咱們進行編寫的類中,默認會給類加上  SerializableAttribute 特性的,固然你也可使用顯式的方式進行添加。當你打算對一個對象進行序列化時,若是它不包含  SerializableAttribute,將會引起異常。在某些時候,咱們可能不但願類中的某些字段或屬性進行序列化操做,你能夠在該字段或屬性上使用  NonSerializedAttribute ,以告訴序列化器不對它們進行序列化操做。
 
  【備註】若是已序列化的類中包含了其餘類對象的引用,而這些類又恰巧也有 SerializableAttribute,那麼它們也會被進行序列化。
  【備註】序列化的關鍵字特性: SerializableAttributeNonSerializedAttribute

 

  這裏介紹一種常見的序列化和一種不常見的序列化:json

  (1)二進制序列化:使用二進制編碼來生成精簡的序列化,會序列化全部成員,並提升性能。經常使用於存儲和 socket 傳輸。跨域

  (2)XML 序列化:可讀性更高,也就表示有更高的靈活性,操做的便利性。可用 XmlSerializer 進行序列化操做。app

 
 

2、經過序列化保存對象數據

  這裏使用 demo 進行簡單演示如何對對象進行序列化和反序列化操做。socket

 

2.1 使用序列化保存對象

 1     [Serializable]  //將類標記爲可序列化
 2     public class Coupon : INotifyPropertyChanged
 3     {
 4         public decimal Amount { get; set; }
 5 
 6         public float InterestRate { get; set; }
 7 
 8         public int Term { get; set; }
 9 
10         private string _name;
11 
12         public string Name
13         {
14             get { return _name; }
15             set
16             {
17                 _name = value;
18                 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Customer"));
19             }
20         }
21 
22         [field: NonSerialized()]    //將可序列化的類中的某字段標記爲不被序列化
23         public event PropertyChangedEventHandler PropertyChanged;
24 
25         public Coupon(decimal amount, float interestRate, int term, string name)
26         {
27             Amount = amount;
28             InterestRate = interestRate;
29             Term = term;
30             _name = name;
31         }
32     }
Coupon.cs
 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             using (var stream = File.Create(fileName))
 7             {
 8                 var deserializer = new BinaryFormatter();  //二進制格式序列化器
 9                 deserializer.Serialize(stream, coupon);  //序列化對象到文件中
10             }
11         }

圖2-1 ide

 

  如今嘗試反序列化,看看與以前 Coupon 對象的值是否一致。性能

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             //var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             //判斷該文件是否存在
 7             if (!File.Exists(fileName))
 8             {
 9                 return;
10             }
11 
12             using (var stream = File.OpenRead(fileName))
13             {
14                 var deserializer = new BinaryFormatter();   //二進制序列化器
15                 var coupon = deserializer.Deserialize(stream) as Coupon;    //反序列化
16 
17                 if (coupon == null)
18                 {
19                     return;
20                 }
21 
22                 Console.WriteLine($"{nameof(Coupon)}:");
23                 Console.WriteLine($"    {nameof(coupon.Amount)}: {coupon.Amount}");
24                 Console.WriteLine($"    {nameof(coupon.InterestRate)}: {coupon.InterestRate}%");
25                 Console.WriteLine($"    {nameof(coupon.Term)}: {coupon.Term}");
26                 Console.WriteLine($"    {nameof(coupon.Name)}: {coupon.Name}");
27             }
28 
29             Console.Read();
30         }

圖2-2ui

 

2.2 使用 SOAP 格式保存對象

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             using (var stream = File.Create(fileName))
 7             {
 8                 var deserializer = new SoapFormatter(); //Soap 格式化器
 9                 deserializer.Serialize(stream, coupon); //序列化
10             }
11         }

圖2-3

  反序列化時也採用 SoapFormatter 便可,結果同圖2-2。

                var deserializer = new SoapFormatter();   //Soap 格式化器
                var coupon = deserializer.Deserialize(stream) as Coupon;    //反序列化

  【注意】不該將這些格式用於敏感數據,如密碼或信用卡信息。

  【備註】二進制格式對於大多數 Windows 應用程序均適用。對於之前來講,使用 Web 應用程序或者是 Web 服務,建議使用 SOAP 的 XML 進行傳輸。而如今,固然是使用大衆化的 json 格式進行傳輸啦。

 

  一樣,也能夠經過 XmlSerializer 將對象序列化保存在 XML 文件。咱們能夠根據需求選擇合適的序列化器,操做基本是同樣的。

 

衆說紛紜

  @hi丶小時候 使用 SerializableAttribute 特性時,是不建議使用自動屬性的,序列化後的字段都是多出 k_BackingField<> 17個字符,若是對象很大會浪費一部分流量,建議使用 DataContractAttribute 和 DataMemberAttribute

  @梁逸晨 除非對方系統強制要求 SOAP 才能通訊,不然該人人抵制這麼反人類的東西,建議樓主 JSON 或 Protobuf

 

 


【參考】https://msdn.microsoft.com/zh-cn/subscriptions/ms233843(v=vs.100).aspx

【參考】微軟官方文檔

相關文章
相關標籤/搜索