C#編程總結(jié)(一)序列化總結(jié)
序列化是將對象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)母袷降倪^程。與序列化相對的是反序列化,它將流轉(zhuǎn)換為對象。這兩個(gè)過程結(jié)合起來,可以輕松地存儲和傳輸數(shù)據(jù)。
幾種序列化技術(shù):
1)二進(jìn)制序列化保持類型保真度,這對于在應(yīng)用程序的不同調(diào)用之間保留對象的狀態(tài)很有用。例如,通過將對象序列化到剪貼板,可在不同的應(yīng)用程序之間共享對象。您可以將對象序列化到流、磁盤、內(nèi)存和網(wǎng)絡(luò)等等。遠(yuǎn)程處理使用序列化“通過值”在計(jì)算機(jī)或應(yīng)用程序域之間傳遞對象。
2)XML 序列化僅序列化公共屬性和字段,且不保持類型保真度。當(dāng)您要提供或使用數(shù)據(jù)而不限制使用該數(shù)據(jù)的應(yīng)用程序時(shí),這一點(diǎn)是很有用的。由于 XML 是一個(gè)開放式標(biāo)準(zhǔn),因此,對于通過 Web 共享數(shù)據(jù)而言,這是一個(gè)很好的選擇。SOAP 同樣是一個(gè)開放式標(biāo)準(zhǔn),這使它也成為一個(gè)頗具吸引力的選擇。
3)使用提供的數(shù)據(jù)協(xié)定,將類型實(shí)例序列化和反序列化為 XML 流或文檔(或者JSON格式)。常應(yīng)用于WCF通信。
BinaryFormatter
序列化可被定義為將對象的狀態(tài)存儲到存儲媒介中的過程。在此過程中,對象的公共字段和私有字段以及類的名稱(包括包含該類的程序集)都被轉(zhuǎn)換為字節(jié)流,然后寫入數(shù)據(jù)流。在以后反序列化該對象時(shí),創(chuàng)建原始對象的精確復(fù)本。
1、使一個(gè)類可序列化的最簡單方式是按如下所示使用 Serializable 屬性標(biāo)記。
2、有選擇的序列化
通過用 NonSerialized 屬性標(biāo)記成員變量,可以防止它們被序列化
3、自定義序列化
1) 在序列化期間和之后運(yùn)行自定義方法
最佳做法也是最簡單的方法(在 .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) 實(shí)現(xiàn) ISerializable 接口
對于用 Serializable 屬性標(biāo)記且在類級別上或其構(gòu)造函數(shù)上具有聲明性或命令性安全的類,不應(yīng)使用默認(rèn)序列化。相反,這些類應(yīng)始終實(shí)現(xiàn) ISerializable 接口。實(shí)現(xiàn) ISerializable 涉及實(shí)現(xiàn) GetObjectData 方法以及在反序列化對象時(shí)使用的特殊構(gòu)造函數(shù)。
具體實(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); } }
注意:
在反序列化一個(gè)對象時(shí)不調(diào)用構(gòu)造函數(shù)。出于性能方面的原因?qū)Ψ葱蛄谢┘恿嗽摷s束。但是,這違反了運(yùn)行庫與對象編寫器之間的一些通常約定,開發(fā)人員應(yīng)確保他們在將對象標(biāo)記為可序列化時(shí)了解其后果。
SoapFormatter
以 SOAP 格式將對象或整個(gè)連接對象的圖形序列化和反序列化。基本用法類似于BinaryFormatter。SoapFormatter 和 BinaryFormatter 兩個(gè)類實(shí)現(xiàn) IRemotingFormatter 接口以支持遠(yuǎn)程過程調(diào)用 (RPC),實(shí)現(xiàn) IFormatter 接口(由 IRemotingFormatter 繼承)以支持對象圖形的序列化。SoapFormatter 類還支持對 ISoapMessage 對象進(jìn)行 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 消息進(jìn)行編碼。
例子:
C#代碼
public class MyClass { public MyObject MyObjectProperty; } public class MyObject { public string ObjectName; }
序列化后的XML
<MyClass> <MyObjectProperty> <ObjectName>My String</ObjectName> </MyObjectProperty> </MyClass>
還可以通過標(biāo)記來控制XML的輸出
1、默認(rèn)值
DefaultValueAttribute
2、過濾某屬性或字段
3、重寫默認(rèn)序列化邏輯
具體可見:http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.xmlattributeoverrides(v=vs.80).aspx
其他控制手段,具體可見http://msdn.microsoft.com/zh-cn/library/83y7df3e(v=vs.80).aspx
4、將對象序列化為 SOAP 編碼的 XML 流
http://msdn.microsoft.com/zh-cn/library/bd04skah(v=vs.80).aspx
注意
XML 序列化不轉(zhuǎn)換方法、索引器、私有字段或只讀屬性(只讀集合除外)。要序列化對象的所有字段和屬性(公共的和私有的),請使用 BinaryFormatter,而不要使用 XML 序列化。
DataContractSerializer
使用提供的數(shù)據(jù)協(xié)定,將類型實(shí)例序列化和反序列化為 XML 流或文檔。 此類不能被繼承。
DataContractSerializer 用于序列化和反序列化在 Windows Communication Foundation (WCF) 消息中發(fā)送的數(shù)據(jù)。 通過將 DataContractAttribute 屬性 (Attribute) 應(yīng)用于類,而將 DataMemberAttribute 屬性 (Attribute) 應(yīng)用于類成員,可以指定要序列化的屬性 (Property) 和字段。
使用步驟:
1)DataContractSerializer 與 DataContractAttribute 和 DataMemberAttribute 類結(jié)合使用。
要準(zhǔn)備序列化某個(gè)類,請將 DataContractAttribute 應(yīng)用于該類。 對于返回要序列化的數(shù)據(jù)的類的每個(gè)成員,請應(yīng)用 DataMemberAttribute。 您可以序列化字段和屬性,而無論其可訪問性級別是什么:private、protected、internal、protected internal 或 public。
2)添加到已知類型的集合中
在序列化或反序列化對象時(shí),DataContractSerializer 必須“已知”該類型。 首先,創(chuàng)建一個(gè)實(shí)現(xiàn) IEnumerable<T>(如 List<T>)的類實(shí)例,并將已知類型添加到集合中。 然后,使用接受 IEnumerable<T>(例如,[M:System.Runtime.Serialization.DataContractSerializer.#ctor(System.Type,System.Collections.Generic.IEnumerable{System.Type}])的重載之一創(chuàng)建 DataContractSerializer 的實(shí)例。
具體實(shí)例:
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序列化 /// 必須類型必須標(biāo)記為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格式,則反序列化報(bào)錯(cuò)??梢杂肈efault格式,不過,建議還是傳參為byte數(shù)組比較好 return Encoding.Default.GetString(bytes); } } /// <summary> /// BinaryFormatter反序列化 /// 必須類型必須標(biāo)記為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序列化 /// 必須類型必須標(biāo)記為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反序列化 /// 必須類型必須標(biāo)記為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 } }
具體的實(shí)例代碼如下:
下載:demo
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# TextBox控件實(shí)現(xiàn)只能輸入數(shù)字的方法
這篇文章主要介紹了C# TextBox控件實(shí)現(xiàn)只能輸入數(shù)字的方法,本文使用TextBox的keypress事件實(shí)現(xiàn)這個(gè)需求,需要的朋友可以參考下2015-06-06Enterprise Library for .NET Framework 2.0緩存使用實(shí)例
這篇文章主要介紹了Enterprise Library for .NET Framework 2.0緩存使用實(shí)例,是進(jìn)行項(xiàng)目開發(fā)時(shí)非常有用的功能,需要的朋友可以參考下2014-08-08C#中Abstract方法和Virtual方法的區(qū)別
這篇文章介紹了C#中Abstract方法和Virtual方法的區(qū)別,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04C# IQueryable及IEnumerable區(qū)別解析
這篇文章主要介紹了C# IQueryable及IEnumerable區(qū)別解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09