當使用Serializable特性,如果類有更新(但有要求和以前序列化的類對象保持相容),可以使用OptionalField特性來標記新加的欄位。至於Serializable特性在類繼承上,問題不會很大,只要父類被標記Serializable特性,那麼子類就可以序列化父類的內容。
而對於ISerializable介面,由於序列化和還原序列化都得自己動手,那麼處理類更新和繼承問題就會稍複雜一些。
比如版本更新,我們可以在SerializationInfo中加入自己的版本資訊,在還原序列化中再根據不同的版本資訊做不同的操作。
下面是一個繼承ISerializable的類型a:
//+ using System.Runtime.Serialization;
[Serializable]
class a : ISerializable
{
int data;
//序列化
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("_版本", 1);
info.AddValue("data", data);
}
//還原序列化
protected a(SerializationInfo info, StreamingContext context)
{
int ver = info.GetInt32("_版本");
if (ver == 1)
data = info.GetInt32("data");
else
throw new SerializationException("不支援的版本");
}
}
如果a又加入了新的欄位,那麼在序列化和反序列話的處理上根據不同版本做不同操作:
//+ using System.Runtime.Serialization;
//更新後的a
[Serializable]
class a : ISerializable
{
int data;
//新加的欄位
int data_ver2;
//序列化
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("_版本", 2);
info.AddValue("data", data);
info.AddValue("data_ver2", data_ver2);
}
//還原序列化
protected a(SerializationInfo info, StreamingContext context)
{
int ver = info.GetInt32("_版本");
//處理舊版本的內容
if (ver >= 1)
data = info.GetInt32("data");
//處理新版本的欄位
else if (ver >= 2)
data_ver2 = info.GetInt32("data_ver2");
else
throw new SerializationException("不支援的版本");
}
}
對於繼承類,注意父類的操作方法要保持對繼承類可見(public或者protected),然後繼承類調用父類的方法就可以了。
代碼:
//+ using System.Runtime.Serialization;
//父類
[Serializable]
class Bcls : ISerializable
{
int id;
//序列化
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("id", id);
}
//還原序列化
protected Bcls(SerializationInfo info, StreamingContext context)
{
id = info.GetInt32("id");
}
}
//繼承類
[Serializable]
class Dcls : Bcls, ISerializable
{
string newdata;
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
//調用父類GetObjectData
base.GetObjectData(info, context);
info.AddValue("newdata", newdata);
}
//調用父類還原序列化建構函式
protected Dcls(SerializationInfo info, StreamingContext context)
: base(info, context)
{
newdata = info.GetString("newdata");
}
}