使用命名空間:
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
串行化類的標誌:在類前加上[Serializable]特性
兩種格式器:BinaryFormatter,SoapFormatter
以BinaryFormatter爲例(SoapFormatter與之相同)
串行化模板:
{
Book myBook = new Book();
BinaryFormatter formatter = new BinaryFormatter();
FileStream fs = File.Create(filename);
formatter.Serialize(fs, myBook);
fs.Close();
}
反串行化模板:
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream fs = File.OpenRead(filename);
Book myBook = (Book)formatter.Deserialize(fs);
fs.Close();
}
*在字段上加上[NonSerialized],可以不使該字段被序列化
*對於引用關係,如果A中引用了B,A和B類都要加上[Serializable],才能對A進行串行化
*對於循環引用,只支持對象圖的循環引用,不支持廣義的對象循環引用
對象圖循環引用的例子:
public class Book
{
private BookCatalog includeInBookCatalog;
public BookCatalog IncludeInBookCatalog
{
get { return includeInBookCatalog; }
set { includeInBookCatalog = value; }
}
}
[Serializable]
public class BookCatalog
{
private Book[] books;
public Book[] Books
{
get { return books; }
set
{
books = value;
foreach (Book book in books)
{
book.IncludeInBookCatalog = this;
}
}
}
}
對BookCatalog進行深度序列化,不會造成循環引用,因爲格式化器Formatter知道無論對象有多少個引用,保證每個對象只串行化一次——通過System.Runtime.Serialization下的兩個類實現:ObjectManager和ObjectIDGenerator。
ObjectManager 負責在對象反串行化時跟蹤對象,確定該對象是否串行化過
ObjectIDGenerator 爲每個被跟蹤的對象加一個唯一的ID以區別,根據對象是否被串行化,ObjectIDGenerator知道是返回已有的ID,還是生成一個新的ID
格式化器不會提前檢查所有的對象可串行化,中途如果發生異常,可以已經生成部分對象了。
通過深串行化克隆對象:
先串行化,在內存流上使用二進制深度複製;然後再找到流的開頭,進行反串行化
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Context = new StreamingContext(StreamingContextStates.Clone);
formatter.Serialize(stream, source);
stream.Position = 0;
return formatter.Deserialize(stream);
}