基本序列化
使類別成為可序列化最容易的方式是,將它以 Serializable 屬性 (Attribute) 標記如下。
[Serializable]
public class MyObject {
public int n1 = 0;
public int n2 = 0;
public String str = null;
}
下面的程式碼範例示範這個類別的執行個體序列化為檔案的方式。
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
這個範例使用二進位格式子來進行序列化。您所要做的是建立資料流的執行個體和您打算使用的格式子,並接著呼叫格式子上的 Serialize 方法。要序列化的資料流和物件將會當作這個呼叫的參數來提供。雖然沒有在這個範例中明確示範,但即使變數被標記為私用的,類別的所有成員變數仍會被序列化。從這個觀點來說,二進位序列化不同於 XMLSerializer 類別,因為後者只序列化公用欄位。如需從二進位序列化排除成員變數的詳細資訊,請參閱選擇性序列化。
將物件還原回到其從前的狀態也是一樣容易。首先,建立供讀取的資料流和格式子,並接著指示格式子將物件還原序列化。下面的程式碼範例說明了進行方式。
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(stream);
stream.Close();
// Here's the proof.
Console.WriteLine("n1: {0}", obj.n1);
Console.WriteLine("n2: {0}", obj.n2);
Console.WriteLine("str: {0}", obj.str);
上面使用的 BinaryFormatter 非常有效率,而且會產生非常精簡的位元組資料流。以這個格式子序列化的所有物件也可以用此格式子來還原序列化,這使得它成為對將會在 .NET Framework 上還原序列化的物件進行序列化的理想工具。重要的是要注意,將物件還原序列化時,不要呼叫建構函式 (Constructor)。這個條件約束 (Constraint) 因效能理由而加諸於還原序列化 (Deserialization)。然而,這違反 Runtime 與物件作者所訂的一些慣常合約,而開發人員在標記物件為可序列化時應該確定他們能夠瞭解這個分歧。
如果可攜性是必要條件,則使用 SoapFormatter 來代替。在上述程式碼中只需以 SoapFormatter 取代 BinaryFormatter,並跟以前一樣呼叫 Serialize 和 Deserialize。這個格式子為上面使用的範例產生下列輸出。
<SOAP-ENV:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP- ENC="https://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP- ENV="https://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle=
"https://schemas.microsoft.com/soap/encoding/clr/1.0"
"https://schemas.xmlsoap.org/soap/encoding/"
xmlns:a1="https://schemas.microsoft.com/clr/assem/ToFile">
<SOAP-ENV:Body>
<a1:MyObject id="ref-1">
<n1>1</n1>
<n2>24</n2>
<str id="ref-3">Some String</str>
</a1:MyObject>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
重要的是要注意,Serializable 屬性無法被繼承。如果您自 MyObject
衍生新類別,新類別也必須以屬性來標記,否則無法序列化。例如,當您嘗試序列化以下類別的執行個體時,您將會收到 SerializationException,告知您 MyStuff
型別沒有標記為可序列化。
public class MyStuff : MyObject
{
public int n3;
}
雖然使用 Serializable 屬性很便利,但它具有上面所示範的限制。請參閱序列化方針中關於何時應該標記類別以供序列化的資訊;序列化在編譯後無法被加入類別。