.Net 中的序列化與反序列化
當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個對象轉換爲字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復爲對象。
把對象轉換爲字節序列的過程稱爲對象的序列化。
把字節序列恢復爲對象的過程稱爲對象的反序列化。
二、對象的序列化主要有兩種用途:
1) 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;
我們經常需要將對象的字段值保存到磁盤中,並在以後檢索此數據。儘管不使用序列化也能完成這項工作,但這種方法通常很繁瑣而且容易出錯,並且在需要跟蹤對象的層次結構時,會變得越來越複雜。可以想象一下編寫包含大量對象的大型業務應用程序的情形,程序員不得不爲每一個對象編寫代碼,以便將字段和屬性保存至磁盤以及從磁 盤還原這些字段和屬性。序列化提供了輕鬆實現這個目標的快捷方法。公共語言運行時 (CLR) 管理對象在內存中的分佈,.NET 框架則通過使用反射提供自動的序列化機制。對象序列化後,類的名稱、程序集以及類實例的所有數據成員均被寫入存儲媒體中。對象通常用成員變量來存儲對其他實例的引用。類序列化後,序列化引擎將跟蹤所有已序列化的引用對象,以確保同一對象不被序列化多次。.NET 框架所提供的序列化體系結構可以自動正確處理對象圖表和循環引用。對對象圖表的唯一要求是,由正在進行序列化的對象所引用的所有對象都必須標記爲 Serializable(請參閱基 本序列化)。否則,當序列化程序試圖序列化未標記的對象時將會出現異常。當反序列化已序列化的類時,將重新創建該類,並自動還原所有數據成員的值。
2) 在網絡上傳送對象的字節序列。
對象僅在創建對象的應用程序域中有效。除非對象是從MarshalByRefObject派生得到或標記爲 Serializable,否則,任何將對象作爲參數傳遞或將其作爲結果返回的嘗試都將失敗。如果對象標記爲 Serializable,則該對象將被自動序列化,並從一個應用程序域傳輸至另一個應用程序域,然後進行反序列化,從而在第二個應用程序域中產生出該對象的一個精確副本。此過程通常稱爲按值封送。如果對象是從MarshalByRefObject派生得到,則從一個應用程序域傳遞至另一個應用程序域的是對象引用,而不是對象本身。也可以將從MarshalByRefObject派生得到的對象標記爲Serializable。遠程使用此對象時,負責進行序列化並已預先配置爲SurrogateSelector的格式化程序將控制序列化過程,並用一個代理替換所有從MarshalByRefObject派生得到的對象。如果沒有預先配置爲SurrogateSelector,序列化體系結構將遵從下面的標準序列化規則.
三、.NET提供了三種序列化方式
[1]、XML Serializer
[2]、SOAP Serializer
[3]、BinarySerializer
四、基本序列化
要使一個類可序列化,最簡單的方法是使用 Serializable 屬性對它進行標記,如下所示:
[Serializable]
public class MyObject
{
public int n1 = 0;
public int n2 = 0;
public String str = null;
}
[BinarySerializer]
將此類的一個實例序列化爲一個文件:
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "一些字符串";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
反序列化:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open,
FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(fromStream);
stream.Close();
[XMLSerializer]
將此類的實例序列化成一個Xml文件.
XmlSerializer ser = new XmlSerializer(obj.GetType());
ser.Serialize(new FileStream(@"users.xml", FileMode.Create), obj);
反序列化:
XmlSerializer serializer = new XmlSerializer(Type.GetType("MyObject"));
MyObject my=(MyObject)serializer.Deserialize(new FileStream(@"users.xml",FileMode.Open));
說明:使用二進制格式化程序進行序列化。您只需創建一個要使用的流和格式化程序的實例,然後調用格式化程序的 Serialize 方法。流和要序列化的對象實例作爲參數提供給此調用。類中的所有成員變量(甚至標記爲 private 的變量)都將被序列化,但這一點在本例中未明確體現出來。在這一點上,二進制序列化不同於只序列化公共字段的 XML 序列化程序。將對象還原到它以前的狀態也非常容易。首先,創建格式化程序和流以進行讀取,然後讓格式化程序對對象進行反序列化。
[SOAP Serializer]
如果要求具有可移植性,請使用 SoapFormatter。所要做的更改只是將以上代碼中的BinaryFormatter換 SoapFormatter,而 Serialize 和 Deserialize 調用不變。