2.基本.NET深串行化
深串行化:串行化对象的整个状态
使用命名空间:
使用命名空间:
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
串行化类的标志:在类前加上[Serializable]特性
两种格式器:BinaryFormatter,SoapFormatter
以BinaryFormatter为例(SoapFormatter与之相同)
串行化模板:
public void SerializeIt(string filename)
{
Book myBook = new Book();
BinaryFormatter formatter = new BinaryFormatter();
FileStream fs = File.Create(filename);
formatter.Serialize(fs, myBook);
fs.Close();
}
{
Book myBook = new Book();
BinaryFormatter formatter = new BinaryFormatter();
FileStream fs = File.Create(filename);
formatter.Serialize(fs, myBook);
fs.Close();
}
反串行化模板:
public void DeserializeIt(string filename)
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream fs = File.OpenRead(filename);
Book myBook = (Book)formatter.Deserialize(fs);
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进行串行化
*对于循环引用,只支持对象图的循环引用,不支持广义的对象循环引用
对象图循环引用的例子:
[Serializable]
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;
}
}
}
}
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
格式化器不会提前检查所有的对象可串行化,中途如果发生异常,可以已经生成部分对象了。
通过深串行化克隆对象:
先串行化,在内存流上使用二进制深度复制;然后再找到流的开头,进行反串行化
public object Clone(object source)
{
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);
}
{
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);
}