序列化是將對象狀態轉換為可保持或傳輸的格式的過程。與序列化相對的是反序列化,它將流轉換為對象。兩個過程結合可以存儲和傳輸數據。
.NET Framework 提供兩種序列化技術:
1) 二進制序列化
這種序列化可以保持類型不變,即可以在應用程序的不同調用之間保留對象的狀態。
2)XML 和SOAP 序列化
這種序列化僅序列化公共屬性和字段,不保存類型。
另外還有Json序列化,需要引用Newtonsoft.Json
1 二進制序列化與反序列化
序列化可被定義為將對象的狀態存儲到存儲媒介中的過程。在此過程中,對象的公共字段和私有字段以及類的名稱(包括該類的程序集)都被轉換為字節流,然后寫入數據流。在以后反序列化該對象時,創建原始對象的精確副本。
序列化有兩個最重要的功能:一個時將對象的狀態保持在存儲媒體中,以便可以在以后重新創建精確的副本;另一個是通過值將對象從一個應用程序域發送到另有一個應用程序域中。例如,序列化可用於在ASP.NET中保存會話狀態並將對象復制到Windows窗體的剪貼板中。遠程處理還可以試用序列化通過將對象從一個程序域傳遞到另一個應用程序域中。
1.1 序列化
序列化一個類最簡單的方式是試用如下所示的Serializable屬性標記。
[Serializable] public class AuthUserEntry { private string accountName; private int accountId; public string AccountName { } public int AccountId { } } }
下面用代碼演示該類的實例是如何被序列化到一個二進制文件(.bin)中的。
AuthUserEntry user = new AuthUserEntry(); user.AccountId = 9912053; user.AccountName = "XinXin"; IFormatter formater = new BinaryFormatter(); Stream stream = new FileStream("UserInfo.bin", FileMode.Create, FileAccess.Write, FileShare.None); formater.Serialize(stream, user); stream.Close();
在這段代碼中,創建流的實例和試用的格式接口后,對該格式接口調用Serialize方法,類中的所有成員變量都將被序列化,即使是哪些已被標記為私有的變量。
1.2 反序列化
要將對象還原回其以前的狀態,首先,創建用於讀取的流和格式化接口,然后用格式化接口反序列化該對象。下面的代碼示例說明如何執行上述的操作
IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream("UserInfo.bin", FileMode.Open, FileAccess.Read, FileShare.Read); AuthUserEntry me = (AuthUserEntry) formatter.Deserialize(stream); stream.Close();
需要特別注意的是,在反序列化一個對象時不調用構造函數。
【例】二進制序列化和反序列化的方法
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; namespace BinarySerializableExample { [Serializable] public class AuthUserEntry { private string accountName; private int accountId; public string AccountName { get { return accountName; } set { accountName = value; } } public int AccountId { get { return accountId; } set { accountId = value; } } } class Account { static void Main(string[] args) { AuthUserEntry user = new AuthUserEntry(); user.AccountId = 9912053; user.AccountName = "XinXin"; IFormatter formater = new BinaryFormatter(); Stream stream = new FileStream("UserInfo.bin", FileMode.Create, FileAccess.Write, FileShare.None); formater.Serialize(stream, user); stream.Close(); stream = new FileStream("UserInfo.bin", FileMode.Open, FileAccess.Read, FileShare.Read); AuthUserEntry me = (AuthUserEntry)formater.Deserialize(stream); stream.Close(); Console.WriteLine("帳戶號:{0}", me.AccountId); Console.WriteLine("帳戶名:{0}", me.AccountName); //按回車鍵結束 Console.ReadLine(); } } }
輸出結果為:
賬號名:9912053
賬戶名:XinXin
打開應用程序的bin文件夾,會看到有一個生成文件UserInfo.bin,打開它會看到正是AuthUserEnty對象實例的值。
1.3 有選擇的序列化
也可能在類中包含不應被序列化的字段。例如,假設一個類將線程ID 存儲在成員變量中。當反序列化該類時,在序列化該類時為其存儲ID 的線程可能不再運行,因此序列化該值沒有意義。通過用NonSerialized 屬性標記成員變量,可以防止它們被序列化,如下所示:
[Serializable] public class MyObject { public int n1; [NonSerialized] public int n2; public String str; }
2 XML和SOAP序列化與反序列化
也可以對XML 和SOAP 流對象進行序列化和反序列化,這種操作一般用於將對象轉換為網絡中容易傳輸的格式。例如,可以序列化一個對象,然后使用HTTP 通過Internet 在客戶端和服務器之間傳輸該對象。在另一端,通過反序列化重新構造對象。
XML 序列化僅將對象的公共字段和屬性值序列化為XML 流,而不轉換方法、索引器、私有字段或只讀屬性(只讀集合除外)。若要序列化對象的所有字段和屬性(公共的和私有的),可以使用BinaryFormatter 序列化。XML 序列化不包括類型信息,即不能保證序列化后的對象在被反序列化時,變為同一類型的對象。
XML序列化中最主要的類是XmlSerializer 類,它的最重要的方法是Serialize 和Deserialize方法。XmlSerializer 生成的XML 流符合萬維網聯合會(www.w3.org)XML 架構定義語言(XSD)的建議。
使用 XmLSerializer 類,可將下列項序列化。
◆ 公共類的公共讀/寫屬性和字段。
◆ 實現 ICollection 或 IEnumerable 的類(注意只有集合會被序列化,而公共屬性卻不會)。
◆ XmlElement 對象。
◆ XmlNode 對象。
◆ DataSet 對象。
2.1 序列化對象
首先,創建要序列化的對象並設置它的公共屬性和字段,而且必須確定用以存儲XML 流的傳輸格式(或者作為流,或者作為文件)。例如,如果XML 流必須以永久形式保存,則創建FileStream 對象。當反序列化對象時,傳輸格式將確定創建流還是文件對象。確定了傳輸格式之后,就可以根據需要調用Serialize 或Deserialize 方法。
其次,使用該對象的類型構造XmlSerializer。
最后,調用Serialize 方法以生成對象的公共屬性和字段的XML 流表示形式或文件表示形式。
下面的示例創建一個文件:
// 第一步,創建要序列化的對象 AuthUserEntry user = new AuthUserEntry(); user.AccountId = 9912053; user.AccountName = "XinXin"; // 第二步,構造XmlSerializer 對象 XmlSerializer mySerializer = new XmlSerializer(typeof(AuthUserEntry)); // 創建StreamWriter 對象完成對文件的寫操作 StreamWriter myWriter = new StreamWriter("UserInfo.xml"); // 第三步,調用Serialize 方法實現序列化 mySerializer.Serialize(myWriter, user); myWriter.Close();
2.2 反序列化對象
首先,使用要反序列化的對象的類型構造XmlSerializer。
其次,調用Deserialize 方法以產生該對象的副本。在反序列化時,必須將返回的對象強制轉換為原始對象的類型。
將對象反序列化為文件的語句為:
AuthUserEntry me; // 用對象類型構造XmlSerializer 的實例 XmlSerializer mySerializer = new XmlSerializer(typeof(AuthUserEntry)); // 創建FileStream 讀取文件 FileStream myFileStream = new FileStream("UserInfo.xml", FileMode.Open); // 調用Deserialize 方法並強制轉換返回對象的類型 me = (AuthUserEntry) mySerializer.Deserialize(myFileStream); myFileStream.Close();
【例】Xml序列化和反序列化的方法
using System; using System.IO; using System.Xml.Serialization; namespace XMLSerializableExample { [Serializable] public class AuthUserEntry { private string accountName; private int accountId; public string AccountName { get { return accountName; } set { accountName = value; } } public int AccountId { get { return accountId; } set { accountId = value; } } } class Account { static void Main(string[] args) { // 第一步,創建要序列化的對象 AuthUserEntry user = new AuthUserEntry(); user.AccountId = 9912053; user.AccountName = "XinXin"; // 第二步,構造XmlSerializer 對象 XmlSerializer mySerializer = new XmlSerializer(typeof(AuthUserEntry)); // 創建StreamWriter 對象完成對文件的寫操作 StreamWriter myWriter = new StreamWriter("UserInfo.xml"); // 第三步,調用Serialize 方法實現序列化 mySerializer.Serialize(myWriter, user); myWriter.Close(); AuthUserEntry me; // 用對象類型構造XmlSerializer 的實例 //XmlSerializer mySerializer = new XmlSerializer(typeof(AuthUserEntry)); // 創建FileStream 讀取文件 FileStream myFileStream = new FileStream("UserInfo.xml", FileMode.Open); // 調用Deserialize 方法並強制轉換返回對象的類型 me = (AuthUserEntry)mySerializer.Deserialize(myFileStream); myFileStream.Close(); Console.WriteLine("帳戶號:{0}", me.AccountId); Console.WriteLine("帳戶名:{0}", me.AccountName); //按回車鍵結束 Console.ReadLine(); } } }
輸出結果為:
帳戶號:9912053
帳戶名:XinXin
打開應用程序的bin 文件夾,會看到有一個生成文件UserInfo.xml,打開它會看到正是AuthUserEntry 對象實例的值。
