標籤:
相關類:
System.SerializableAttribute特性(或稱為屬性),
System.Runtime.Serialization.Iserializable(自訂序列化介面),
System.Runtime.Serialization.IserializationSurrogate(自訂序列化代理介面),
System.Runtime.Serializatin.SurrogateSelector(自訂序列化代理設定類)
1:官方備忘
序列化使用
BinaryFormatter(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx)或
SopaFormatter(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatters.soap.soapformatter.aspx),使用方法類同。
System.SerializableAttribute特性:
將SerializableAttribute特性應用於一個類型可指示該類型的執行個體可以序化。如果正在序列化的對象圖中的人呢和烈性未應用 SerializableAttribute特性,通用語言執行平台則會引發SerializableException(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.serializationexception.aspx)。
即 使該類也會實現Iserializable(https://msdn.microsoft.com/zh-cn/library /system.runtime.serialization.iserializable.aspx)介面來控制序列化進程,仍要應用 SerializableAttribute特性。
將SerializableAttribute特性應用於類型時,序列化預設情況下所有私人和公用欄位。您可以通過實現介面Iserializable重寫序列化控制項序列化granularly處理。
也可以從序列化排除欄位通過應用NonSerializedAttribute(https://msdn.microsoft.com/zh-cn/library/system.nonserializedattribute.aspx)特性應用於欄位。如果可序列化類別型的欄位包含指標、控制代碼或其他模型針對於特定環境的資料結構,並且不能再不同的環境中以有異議的方式重建,則最好經NonSerializableAttribute特性應用於該欄位。
System.Runtime.Serialization.Iserializable介面:
任何可以序列化的類都必須用SerializableAttribute進行標記。如果某個類需要控制器序列化進程,它可以實現Iserializable介面。Formatter(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatter.aspx)在序列化時調用GetObjectData(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.iserializable.getobjectdata.aspx),並使用表示對象所需的全部資料來填充所提供的SerializationInfo(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.serializationinfo.aspx)。 Formatter使用圖形中對象的類型來建立SerializationInfo。需要自己發送代理的對象可以使用SerializationInfo 上的FullTypeName(https://msdn.microsoft.com/zh-cn/library /system.runtime.serialization.serializationinfo.fulltypename.aspx)和 AssemblyName(https://msdn.microsoft.com/zh-cn/library /system.runtime.serialization.serializationinfo.assemblyname.aspx)方法來更改所 傳輸的資訊。
在類繼承的情況下,可以序列化從實現Iserializable的基類中派生的類。這種情況下,派生的類應在GetObjectData的實現內調用GetObjectData的基類實現。否則,不會序列化來自基類的資料。
Iserializable 介面表示帶有簽字(SerializationInfo,StreamingContext)的建構函式。在還原序列化時,僅在格式化程式已還原序列化 SerializationInfo中的資料後才調用當前建構函式。一般而言,如果該類未密封,則應保護此建構函式。
無法保證對象被反序列 化的順序。例如,如果一種類型引用尚未還原序列化的類型,則會引發異常。如果建立具有這種依賴關係的類型,可以通過 IDeserializationCallback(https://msdn.microsoft.com/zh-cn/library /system.runtime.serialization.ideserializationcallback.aspx)介面和 OnDeserialization方法來解決該問題。
序列化介面處理像處理擴充Object的類型一樣,處理擴充MarshalByRefObject(https://msdn.microsoft.com/zh-cn/library/system.marshalbyrefobject.aspx)的物件類型。這些類型都可以使用SerializableAttribute來標記,並且可以將Iserializable介面實現為其他任何物件類型。它們的對象狀態將被捕獲並在流中持續。
當 通過System.Runtime.Remotting使用這些類型時,遠端介面會提供一個代理項,它將取代常用的序列化,而將代理序列化為 MarshalByRefObject。代理項是知道如何將特定類型的對象序列化和還原序列化的協助器。代理在大多數情況下對使用者不可見,其類型將是 ObjRef(https://msdn.microsoft.com/zh-cn/library /system.runtime.remoting.objref.aspx)。
作為一種常規的設計模式,類很少會既使用可序列化特性來標記,又擴充MarshalByRefObject。當組合這兩項特性時,開發人員應仔細考慮可能的序列化和遠端方案。MemoryStream(https://msdn.microsoft.com/zh-cn/library/system.io.memorystream.aspx)就是一個適用的樣本。當MemoryStream的基類從MarshalByRefObject擴充時,可以捕獲MemoryStream的狀態並隨時將其還原。因此,這樣做可能是有意義的:將該流的狀態序列化到資料庫中,並在稍後某一時間將其還原。但是,當通過遠端來使用時,這種類型的對象將設定代理。
有 關序列化MarshalByRefObject的衍生類別的更多資訊,請參見 RemottingSurrogateSelector(https://msdn.microsoft.com/zh-cn/library /system.runtime.remoting.messaging.remotingsurrogateselector.aspx)。關於如果實 現Iserializable的更多資訊,請參見自訂序列化(https://msdn.microsoft.com/zh-cn/library/ty01x675.aspx)。
System.Runtime.Serialization.IserializationSurrogate介面:
實現序列化代理選取器,此選取器允許一個對象對另一個對象執行序列化和還原序列化。
System.Runtime.Serializatin.SurrogateSelector類:
序列化代理項將為使用者提供一種對象,該對象可以處理不同對象的序列化要求,並且可以再必要時轉換序列化資料。該類實現介面System.Runtime.Serializatin.IsurrogateSelector。
System.Runtime.Serializatin.IsurrogateSelector介面:
代理項選取器實現IsurrogateSelector介面以協助格式化程式選擇代理項以委託給其他對象的序列化或還原序列化。
2:簡單序列化
需要使用的類有SerializableAttribute特性,和BinaryFormatter,對於不需要或不應序列化的類成員需用NonSerializableAttribute特性修飾。
代碼如下:
[Serializable]
public class MyItemType{
//其他成員…
[NonSerializable]
public string IgnorField{…}
}
//序列化過程
string fileName = “[檔案名稱]”;
MyItemType t = new MyItemType();
FileStream fs = new FileStream(fileName,FileMode.Create);
IFromatter formatter = new BinaryFormatter();
formatter.Serialize(fs, t);
fs.Close();
//還原序列化過程
string fileName = “[檔案名稱]”;
MyItemType result = null;
FileStream fs = new FileStream(fileName, FileMode.Open);
IFormatter formatter = new BinaryFormatter();
result = formatter.Deserialize(fs);
fs.Close();
3:使用Iserializable介面實現自訂序列化
繼承Iserializable介面需實現方法GetObjectData,並添加一個具有簽名SerializationInfo info和StreamingContext context的構造方法以供還原序列化使用,須注意的是此構造方法的存取修飾詞在還原序列化過程中將被忽略,因此為防止此構造方法被錯誤的調用應對其使用較 嚴格的存取修飾詞比如protected或private。
實現此介面的類也應當使用SerializableAttribute修飾。
代碼執行個體:
[Serializable]
public class MyItemType:Isereializable
{
//欄位….
#region 自訂序列化
private MyItemType(SerializationInfo info, StreamingContext context)
{
ThisObjectStringField = info.GetValue(“keyName”, typeof(string));
ThisObjectIntField = info.GetInt32(“keyName2”);
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(“keyName”, ThisObjectStringField, typeof(string));
//info.AddInt32(“keyName”, ThisObjectIntField);//此行錯誤,info沒有強型別的值添加方法
}
#endregion
}
//使用方法同於簡單序列化代碼執行個體中的使用方法
4:使用IserializationSurrogate介面實現的序列化代理項
使用IserializationSurrogate實作類別可對另一個類進行序列化和還原序列化。
此序列化方式使用到的類或介面還包括對代理項選擇的SurrogateSelector類,Iformatter實作類別(此處使用BinaryFormatter)
範例程式碼:
//自訂序列化代理
public class Surrogate : ISerializationSurrogate
{
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
if (obj is MyItemType)
{
MyItemType temp = (MyItemType)obj;
info.AddValue("props", temp, typeof(string));
}
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
if (obj is MyItemType)
{
MyItemType temp = (MyItemType)obj;
temp.MyProperty = (string)info.GetValue("props", typeof(string));
Console.WriteLine("SetObjectData");
return temp;
}
return null;
}
//使用方法
Surrogate surrogate = new Surrogate();
SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate(typeof(MyItemType), new StreamingContext(StreamingContextStates.All), surrogate);
formatter.SurrogateSelector = selector;
FileStream fs = new FileStream(fileName, FileMode.Open);
formatter.Deserialize(fs);
fs.Close();
//總結時間:2015/3/17
C#序列化與還原序列化方式簡單總結