c#序列化詳解示例
幾種序列化技術(shù):
1)二進制序列化保持類型保真度,這對于在應(yīng)用程序的不同調(diào)用之間保留對象的狀態(tài)很有用。例如,通過將對象序列化到剪貼板,可在不同的應(yīng)用程序之間共享對象。您可以將對象序列化到流、磁盤、內(nèi)存和網(wǎng)絡(luò)等等。遠程處理使用序列化“通過值”在計算機或應(yīng)用程序域之間傳遞對象。
2)XML 序列化僅序列化公共屬性和字段,且不保持類型保真度。當(dāng)您要提供或使用數(shù)據(jù)而不限制使用該數(shù)據(jù)的應(yīng)用程序時,這一點是很有用的。由于 XML 是一個開放式標準,因此,對于通過 Web 共享數(shù)據(jù)而言,這是一個很好的選擇。SOAP 同樣是一個開放式標準,這使它也成為一個頗具吸引力的選擇。
3)使用提供的數(shù)據(jù)協(xié)定,將類型實例序列化和反序列化為 XML 流或文檔(或者JSON格式)。常應(yīng)用于WCF通信。
BinaryFormatter
序列化可被定義為將對象的狀態(tài)存儲到存儲媒介中的過程。在此過程中,對象的公共字段和私有字段以及類的名稱(包括包含該類的程序集)都被轉(zhuǎn)換為字節(jié)流,然后寫入數(shù)據(jù)流。在以后反序列化該對象時,創(chuàng)建原始對象的精確復(fù)本。
1、使一個類可序列化的最簡單方式是按如下所示使用 Serializable 屬性標記。
2、有選擇的序列化
通過用 NonSerialized 屬性標記成員變量,可以防止它們被序列化
3、自定義序列化
1) 在序列化期間和之后運行自定義方法
最佳做法也是最簡單的方法(在 .Net Framework 2.0 版中引入),就是在序列化期間和之后將下列屬性應(yīng)用于用于更正數(shù)據(jù)的方法:
OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
OnSerializingAttribute
具體事例如下:
// This is the object that will be serialized and deserialized.
[Serializable()]
public class TestSimpleObject
{
// This member is serialized and deserialized with no change.
public int member1;
// The value of this field is set and reset during and
// after serialization.
private string member2;
// This field is not serialized. The OnDeserializedAttribute
// is used to set the member value after serialization.
[NonSerialized()]
public string member3;
// This field is set to null, but populated after deserialization.
private string member4;
// Constructor for the class.
public TestSimpleObject()
{
member1 = 11;
member2 = "Hello World!";
member3 = "This is a nonserialized value";
member4 = null;
}
public void Print()
{
Console.WriteLine("member1 = '{0}'", member1);
Console.WriteLine("member2 = '{0}'", member2);
Console.WriteLine("member3 = '{0}'", member3);
Console.WriteLine("member4 = '{0}'", member4);
}
[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context)
{
member2 = "This value went into the data file during serialization.";
}
[OnSerialized()]
internal void OnSerializedMethod(StreamingContext context)
{
member2 = "This value was reset after serialization.";
}
[OnDeserializing()]
internal void OnDeserializingMethod(StreamingContext context)
{
member3 = "This value was set during deserialization";
}
[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context)
{
member4 = "This value was set after deserialization.";
}
}
2) 實現(xiàn) ISerializable 接口
對于用 Serializable 屬性標記且在類級別上或其構(gòu)造函數(shù)上具有聲明性或命令性安全的類,不應(yīng)使用默認序列化。相反,這些類應(yīng)始終實現(xiàn) ISerializable 接口。實現(xiàn) ISerializable 涉及實現(xiàn) GetObjectData 方法以及在反序列化對象時使用的特殊構(gòu)造函數(shù)。
具體實例如下:
[Serializable]
public class MyObject : ISerializable
{
public int n1;
public int n2;
public String str;
public MyObject()
{
}
protected MyObject(SerializationInfo info, StreamingContext context)
{
n1 = info.GetInt32("i");
n2 = info.GetInt32("j");
str = info.GetString("k");
}
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter
=true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("i", n1);
info.AddValue("j", n2);
info.AddValue("k", str);
}
}
注意:
在反序列化一個對象時不調(diào)用構(gòu)造函數(shù)。出于性能方面的原因?qū)Ψ葱蛄谢┘恿嗽摷s束。但是,這違反了運行庫與對象編寫器之間的一些通常約定,開發(fā)人員應(yīng)確保他們在將對象標記為可序列化時了解其后果。
SoapFormatter
以 SOAP 格式將對象或整個連接對象的圖形序列化和反序列化?;居梅愃朴贐inaryFormatter。SoapFormatter 和 BinaryFormatter 兩個類實現(xiàn) IRemotingFormatter 接口以支持遠程過程調(diào)用 (RPC),實現(xiàn) IFormatter 接口(由 IRemotingFormatter 繼承)以支持對象圖形的序列化。SoapFormatter 類還支持對 ISoapMessage 對象進行 RPC,而不必使用 IRemotingFormatter 功能。
XmlSerializer
將對象序列化到 XML 文檔中和從 XML 文檔中反序列化對象。XmlSerializer 使您得以控制如何將對象編碼到 XML 中。
XML 序列化是將對象的公共屬性 (Property) 和字段轉(zhuǎn)換為序列格式(這里是指 XML)以便存儲或傳輸?shù)倪^程。反序列化則是從 XML 輸出中重新創(chuàng)建原始狀態(tài)的對象。因此,可以將序列化視為將對象的狀態(tài)保存到流或緩沖區(qū)的方法。例如,ASP.NET 使用 XmlSerializer 類對 XML Web services 消息進行編碼。
例子:
C#代碼
public class MyClass
{
public MyObject MyObjectProperty;
}
public class MyObject
{
public string ObjectName;
}
序列化后的XML
<MyClass>
<MyObjectProperty>
<ObjectName>My String</ObjectName>
</MyObjectProperty>
</MyClass>
還可以通過標記來控制XML的輸出
1、默認值
DefaultValueAttribute
2、過濾某屬性或字段
XmlIgnoreAttribute
3、重寫默認序列化邏輯
4、將對象序列化為 SOAP 編碼的 XML 流
注意
XML 序列化不轉(zhuǎn)換方法、索引器、私有字段或只讀屬性(只讀集合除外)。要序列化對象的所有字段和屬性(公共的和私有的),請使用 BinaryFormatter,而不要使用 XML 序列化。
DataContractSerializer
使用提供的數(shù)據(jù)協(xié)定,將類型實例序列化和反序列化為 XML 流或文檔。 此類不能被繼承。
DataContractSerializer 用于序列化和反序列化在 Windows Communication Foundation (WCF) 消息中發(fā)送的數(shù)據(jù)。 通過將 DataContractAttribute 屬性 (Attribute) 應(yīng)用于類,而將 DataMemberAttribute 屬性 (Attribute) 應(yīng)用于類成員,可以指定要序列化的屬性 (Property) 和字段。
使用步驟:
1)DataContractSerializer 與 DataContractAttribute 和 DataMemberAttribute 類結(jié)合使用。
要準備序列化某個類,請將 DataContractAttribute 應(yīng)用于該類。 對于返回要序列化的數(shù)據(jù)的類的每個成員,請應(yīng)用 DataMemberAttribute。 您可以序列化字段和屬性,而無論其可訪問性級別是什么:private、protected、internal、protected internal 或 public。
2)添加到已知類型的集合中
在序列化或反序列化對象時,DataContractSerializer 必須“已知”該類型。 首先,創(chuàng)建一個實現(xiàn) IEnumerable<T>(如 List<T>)的類實例,并將已知類型添加到集合中。 然后,使用接受 IEnumerable<T>(例如,[M:System.Runtime.Serialization.DataContractSerializer.#ctor(System.Type,System.Collections.Generic.IEnumerable{System.Type}])的重載之一創(chuàng)建 DataContractSerializer 的實例。
具體實例:
namespace DataContractSerializerExample
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Xml;
// You must apply a DataContractAttribute or SerializableAttribute
// to a class to have it serialized by the DataContractSerializer.
[DataContract(Name = "Customer", Namespace = "http://www.contoso.com")]
class Person : IExtensibleDataObject
{
[DataMember()]
public string FirstName;
[DataMember]
public string LastName;
[DataMember()]
public int ID;
public Person(string newfName, string newLName, int newID)
{
FirstName = newfName;
LastName = newLName;
ID = newID;
}
private ExtensionDataObject extensionData_Value;
public ExtensionDataObject ExtensionData
{
get
{
return extensionData_Value;
}
set
{
extensionData_Value = value;
}
}
}
public sealed class Test
{
private Test() { }
public static void Main()
{
try
{
WriteObject("DataContractSerializerExample.xml");
ReadObject("DataContractSerializerExample.xml");
}
catch (SerializationException serExc)
{
Console.WriteLine("Serialization Failed");
Console.WriteLine(serExc.Message);
}
catch (Exception exc)
{
Console.WriteLine(
"The serialization operation failed: {0} StackTrace: {1}",
exc.Message, exc.StackTrace);
}
finally
{
Console.WriteLine("Press <Enter> to exit....");
Console.ReadLine();
}
}
public static void WriteObject(string fileName)
{
Console.WriteLine(
"Creating a Person object and serializing it.");
Person p1 = new Person("Zighetti", "Barbara", 101);
FileStream writer = new FileStream(fileName, FileMode.Create);
DataContractSerializer ser =
new DataContractSerializer(typeof(Person));
ser.WriteObject(writer, p1);
writer.Close();
}
public static void ReadObject(string fileName)
{
Console.WriteLine("Deserializing an instance of the object.");
FileStream fs = new FileStream(fileName,
FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(Person));
// Deserialize the data and read it from the instance.
Person deserializedPerson =
(Person)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
Console.WriteLine(String.Format("{0} {1}, ID: {2}",
deserializedPerson.FirstName, deserializedPerson.LastName,
deserializedPerson.ID));
}
}
DataContractJsonSerializer
將對象序列化為 JavaScript 對象表示法 (JSON),并將 JSON 數(shù)據(jù)反序列化為對象。 此類不能被繼承。
具體使用與DataContractSerializer類似。這里不再贅述。
下面對這些方法的使用做了匯總,希望能給大家?guī)硪恍椭?/P>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Xml.Serialization;
namespace SerializerSample
{
/// <summary>
/// 序列化幫助類
/// </summary>
public sealed class SerializeHelper
{
#region DataContract序列化
/// <summary>
/// DataContract序列化
/// </summary>
/// <param name="value"></param>
/// <param name="knownTypes"></param>
/// <returns></returns>
public static string SerializeDataContract(object value, List<Type> knownTypes = null)
{
DataContractSerializer dataContractSerializer = new DataContractSerializer(value.GetType(), knownTypes);
using (MemoryStream ms = new MemoryStream())
{
dataContractSerializer.WriteObject(ms, value);
ms.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(ms))
{
return sr.ReadToEnd();
}
}
}
/// <summary>
/// DataContract反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml"></param>
/// <returns></returns>
public static T DeserializeDataContract<T>(string xml)
{
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
#endregion
#region DataContractJson序列化
/// <summary>
/// DataContractJson序列化
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string SerializeDataContractJson(object value)
{
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(value.GetType());
using (MemoryStream ms = new MemoryStream())
{
dataContractSerializer.WriteObject(ms, value);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
/// <summary>
/// DataContractJson反序列化
/// </summary>
/// <param name="type"></param>
/// <param name="str"></param>
/// <returns></returns>
public static object DeserializeDataContractJson(Type type, string str)
{
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(type);
using (MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(str)))
{
return dataContractSerializer.ReadObject(ms);
}
}
/// <summary>
/// DataContractJson反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json"></param>
/// <returns></returns>
public T DeserializeDataContractJson<T>(string json)
{
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
return (T)dataContractSerializer.ReadObject(ms);
}
}
#endregion
#region XmlSerializer序列化
/// <summary>
/// 將對象序列化到 XML 文檔中和從 XML 文檔中反序列化對象。XmlSerializer 使您得以控制如何將對象編碼到 XML 中。
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string SerializeXml(object value)
{
XmlSerializer serializer = new XmlSerializer(value.GetType());
using (MemoryStream ms = new MemoryStream())
{
serializer.Serialize(ms, value);
ms.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(ms))
{
return sr.ReadToEnd();
}
}
}
/// <summary>
/// XmlSerializer反序列化
/// </summary>
/// <param name="type"></param>
/// <param name="str"></param>
/// <returns></returns>
public static object DeserializeXml(Type type, string str)
{
XmlSerializer serializer = new XmlSerializer(type);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
using (MemoryStream ms = new MemoryStream(bytes))
{
return serializer.Deserialize(ms);
}
}
#endregion
#region BinaryFormatter序列化
/// <summary>
/// BinaryFormatter序列化
/// 必須類型必須標記為Serializable
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string SerializeBinaryFormatter(object obj)
{
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms,obj);
byte[] bytes = ms.ToArray();
obj = formatter.Deserialize(new MemoryStream(bytes));
//如果是UTF8格式,則反序列化報錯??梢杂肈efault格式,不過,建議還是傳參為byte數(shù)組比較好
return Encoding.Default.GetString(bytes);
}
}
/// <summary>
/// BinaryFormatter反序列化
/// 必須類型必須標記為Serializable
/// </summary>
/// <param name="serializedStr"></param>
/// <returns></returns>
public static T DeserializeBinaryFormatter<T>(string serializedStr)
{
BinaryFormatter formatter = new BinaryFormatter();
byte[] bytes = Encoding.Default.GetBytes(serializedStr);
using (MemoryStream ms = new MemoryStream(bytes))
{
return (T)formatter.Deserialize(ms);
}
}
#endregion
#region SoapFormatter序列化
/// <summary>
/// SoapFormatter序列化
/// 必須類型必須標記為Serializable
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string SerializeSoapFormatter(object obj)
{
SoapFormatter formatter = new SoapFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, obj);
byte[] bytes = ms.ToArray();
return Encoding.UTF8.GetString(bytes);
}
}
/// <summary>
/// SoapFormatter反序列化
/// 必須類型必須標記為Serializable
/// </summary>
/// <param name="serializedStr"></param>
/// <returns></returns>
public static T DeserializeSoapFormatter<T>(string serializedStr)
{
SoapFormatter formatter = new SoapFormatter();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(serializedStr)))
{
return (T)formatter.Deserialize(ms);
}
}
#endregion
}
}
相關(guān)文章
macOS系統(tǒng)下Vscode的python配置教程
這篇文章主要介紹了macOS系統(tǒng)下Vscode的python配置教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04C#實現(xiàn)win10 uwp 右擊浮出窗在點擊位置
本文主要讓MenuFlyout出現(xiàn)在我們右擊位置。我們建一個ListView,然后綁定后臺,在我們ListView要右擊顯示我們的浮出,要求我們的浮出在我們點擊位置2016-10-10C# 漢字轉(zhuǎn)拼音實例(支持GB2312字符集中所有漢字)
本篇文章主要介紹了C# 漢字轉(zhuǎn)拼音實例(支持GB2312字符集中所有漢字) ,非常具有實用價值,需要的朋友可以參考下。2016-12-12Unity的BuildPlayerProcessor實用案例深入解析
這篇文章主要為大家介紹了Unity的BuildPlayerProcessor實用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05