?? 序列化機制.txt
字號:
?
+
Remoting:于.net框架下的序列化機制
程序員在編寫應用程序的時候往往要將程序的某些數據存儲在內存中,然后將其寫入某個文件或是將它傳輸到網絡中的另一臺計算機上以實現通訊。這個將程序數據轉化成能被存儲并傳輸的格式的過程被稱為"序列化"(Serialization),而它的逆過程則可被稱為"反序列化"(Deserialization)。
.net框架對序列化機制具有非常好的支持,它提供了兩個名字空間(namespace):System.Runtime.Serialization和System.Runtime.Serialization.Formatters以完成序列化機制的大部分功能。系列化這項技術可以應用在將程序產生的結果數據存儲到文件系統中,但是它更主要的應用是在于.Net Remoting和Web服務的實現上。
序列化機制的實現是依靠格式器(Formatter)而完成的,它是一個從System.Runtime.Serialization.IFormatter繼承下來的類的對象。格式器完成了將程序數據轉化到能被存儲并傳輸的格式的工作,同時也完成了將數據轉化回來的工作。.Net框架為程序員提供了兩種類型的格式器,一種通常是應用于桌面類型的應用程序的,它一個是System.Runtime.Serialization.Formatters.Binary.BinaryFormatter類的對象,而另一種則更主要的應用于.Net Remoting和XML Web服務等領域的,它一個是System.Runtime.Serialization.Formatters.Soap.SoapFormatter類的對象。從它們的名稱來看,我們不妨將它們分別稱為二進制格式器和XML格式器。
本文將從這兩個格式器入手,先向大家介紹分別用它們如何實現序列化和反序列化,然后比較兩種格式器的不同點。接著我會向大家介紹實現序列化對對象類型的一些要求,同時還要向大家介紹兩種不同的序列化方式:基本序列化(Basic Serialization)和自定義序列化(Custom Serialization)。最后,我還會給大家介紹一個實例程序以加深大家對序列化機制的理解程度。
一.二進制格式器(Binary Formatter) vs XML格式器(XML Formatter):
下面我先向大家介紹兩種不同的格式器,分別用它們如何實現序列化機制和反序列化機制,請看下面的代碼:
#region Binary Serializers
public static System.IO.MemoryStream SerializeBinary(object request) {
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
serializer.Serialize(memStream, request);
return memStream;
}
public static object DeSerializeBinary(System.IO.MemoryStream memStream) {
memStream.Position=0;
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter deserializer =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
object newobj = deserializer.Deserialize(memStream);
memStream.Close();
return newobj;
}
#endregion
#region XML Serializers
public static System.IO.MemoryStream SerializeSOAP(object request) {
System.Runtime.Serialization.Formatters.Soap.SoapFormatter serializer =
new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
serializer.Serialize(memStream, request);
return memStream;
}
public static object DeSerializeSOAP(System.IO.MemoryStream memStream) {
object sr;
System.Runtime.Serialization.Formatters.Soap.SoapFormatter deserializer =
new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
memStream.Position=0;
sr = deserializer.Deserialize(memStream);
memStream.Close();
return sr;
}
#endregion
從上面的代碼我們可以發現無論運用哪種格式器,其基本的過程都是一樣的,而且都是非常容易實現的,唯一的不同就是定義格式器的類型不同。不過在實際的應用中,二進制格式器往往應用于一般的桌面程序和網絡通訊程序中,而XML格式器稟承了XML技術的優點,大多數被應用于.Net Remoting和XML Web服務等領域。下面我們來分析一下兩種格式器各自的優點。
二進制序列化的優點:
1. 所有的類成員(包括只讀的)都可以被序列化;
2. 性能非常好。
XML序列化的優點:
1. 互操作性好;
2. 不需要嚴格的二進制依賴;
3. 可讀性強。
通過分析上面的代碼,我們知道了選擇二進制序列化的方式還是選擇XML序列化的方式僅僅是對不同的格式器進行選擇而已。你可以根據實際的需要選擇相應的格式器完成序列化和反序列化工作。同時請注意,代碼中的序列化函數和反序列化函數僅僅是在調用Serialize()和Deserialize()這兩個核心函數上產生了差別,即它們的參數不同。因此以上的代碼完成了一些最最基本但是很重要的功能,你可以將它們運用在你的程序中,或是將其進行適當擴充以滿足程序的特定需要。
二.序列化機制對類的要求:
如果你要對一個對象進行序列化,那么你必須將它的類型標記為[Serializable()],該操作是通過SerializableAttribute屬性來實現的。將SerializableAttribute屬性應用于一種數據類型可表明該數據類型的實例可以被序列化。如果正在序列化的對象圖中的任何類型未應用SerializableAttribute屬性,公共語言運行庫則會引發SerializationException。默認情況下,類型中由SerializableAttribute標記的所有公共和私有字段都會進行序列化,除非該類型實現ISerializable接口來重寫序列化進程(通過實現該接口我們便可以實現將在后面介紹的"自定義序列化")。默認的序列化進程會排除用NonSerializedAttribute屬性標記的字段,即你可以將該類型標記為[NonSerialized()]以表明它是不可以被序列化的。如果可序列化類型的字段包含指針、句柄或其他某些針對于特定環境的數據結構,并且不能在不同的環境中以有意義的方式重建,則最好將NonSerializedAttribute屬性應用于該字段。有關序列化的更多信息,請參閱System.Runtime.Serialization名字空間中的相關內容。
下面我給大家介紹一個例子,以顯示如何正確的運用SerializableAttribute屬性和NonSerializedAttribute屬性。該程序中運用到了XML格式器,不過同時給出了二進制格式器為參考(程序中將其用"//"標注),其實現的結果是一樣的。該程序實現的功能是在序列化和反序列化操作前后測試對象因包含了[NonSerialized()]的字段而顯示不同的屏幕打印結果。其代碼如下:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
//using System.Runtime.Serialization.Formatters.Binary;
public class Test {
public static void Main() {
// 創建一個新的測試對象
TestSimpleObject obj = new TestSimpleObject();
Console.WriteLine("Before serialization the object contains: ");
obj.Print();
// 創建一個文件"data.XML"并將對象序列化后存儲在其中
Stream stream = File.Open("data.xml", FileMode.Create);
SoapFormatter formatter = new SoapFormatter();
//BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Close();
// 將對象置空
obj = null;
// 打開文件"data.xml"并進行反序列化得到對象
stream = File.Open("data.xml", FileMode.Open);
formatter = new SoapFormatter();
//formatter = new BinaryFormatter();
obj = (TestSimpleObject)formatter.Deserialize(stream);
stream.Close();
Console.WriteLine("");
Console.WriteLine("After deserialization the object contains: ");
obj.Print();
}
}
// 一個要被序列化的測試對象的類
[Serializable()]
public class TestSimpleObject {
public int member1;
public string member2;
public string member3;
public double member4;
// 標記該字段為不可被序列化的
[NonSerialized()] public string member5;
public TestSimpleObject() {
member1 = 11;
member2 = "hello";
member3 = "hello";
member4 = 3.14159265;
member5 = "hello world!";
}
public void Print() {
Console.WriteLine("member1 = '{0}'", member1);
Console.WriteLine("member2 = '{0}'", member2);
Console.WriteLine("member3 = '{0}'", member3);
Console.WriteLine("member4 = '{0}'", member4);
Console.WriteLine("member5 = '{0}'", member5);
}
}
三.基本序列化(Basic Serialization) vs 自定義序列化(Custom Serialization):
.net框架為我們提供了兩種方式的序列化:一種為基本序列化、另一種為自定義序列化。值得注意的是,序列化的方式和前面提到的序列化的格式是不同的概念。序列化的方式是指.Net框架將程序的數據轉化為能被存儲并傳輸的格式的實際過程,它是不管程序員運用了何種類型的格式器的(二進制格式器還是XML格式器)。而序列化的格式則指程序的數據是被轉化成二進制格式了還是被轉化成XML格式了。
完成序列化的最簡單的方法便是讓.Net框架自動為我們完成整個過程,而我們不必去管它內部是如何具體實現的,這種方法便是前面提到的"基本序列化"。在這種方式下,我們需要做的僅僅是將類標記上[Serializable()]屬性。然后.Net框架便調用該類的對象并將它轉化為所需的格式。同時你還可以控制其中的某些字段不被序列化,方法就是前面所述的將該字段標記上[NonSerialized()]屬性。這樣,最最簡單和基本的序列化工作就完成了,不過其內部是如何實現的你是不得而知的,同時你也不能進一步控制序列化過程的程序行為。
如果你要獲得對序列化的更大的控制權,那么你就得使用"自定義序列化"的方式。通過使用這種方式,你可以完全的控制類的哪些部分能被序列化而哪些部分不能,同時你還可以控制如何具體的進行序列化。運用該方式的好處就是能克服基本序列化所會遇到的問題。我們在運用基本序列化將一個類的對象序列化完畢并存儲在文件中后,假設該對象原來有三個字段,如果此時該對象增加了一個字段,那么再將該對象從文件中反序列化出來時會發生字段數不一致的錯誤。這樣的問題是基本序列化所不能解決的,只能運用自定義序列化的方式來解決。
在介紹自定義序列化之前,我先給出介紹過程中所要用到的實例程序的代碼。這是一個時間安排程序,其中要用到將不同的時間格式進行轉化的操作。所以運用序列化的機制能很好的解決這個問題。
using System;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -