序列化和反序列化的幾種方式(DataContractSerializer)(二)


DataContractSerializer

     使用提供的數據協定,將類型實例序列化和反序列化為 XML 流或文檔。 無法繼承此類。

命名空間: System.Runtime.Serialization
程序集:  System.Runtime.Serialization(在 System.Runtime.Serialization.dll 中)

備注

     使用 DataContractSerializer 類可以將類型實例序列化和反序列化為 XML 流或文檔。 通過將 DataContractAttribute 特性應用於類,而將DataMemberAttribute 特性應用於類成員,可以指定要序列化的屬性和字段。

      從字面意思來理解就是:數據契約序列化,本文主要是講解用DataContractSerializer 序列化和反序列化,關於它在WCF中的應用大家可以參考《WCF全面解析上冊 蔣金楠著》第五章 序列化,里面有專門的介紹。

DataContractAttribute與DataMenmberAttribute

 1 #region 程序集 System.Runtime.Serialization.dll, v4.0.0.0
 2 // C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Runtime.Serialization.dll
 3 #endregion
 4 
 5 using System;
 6 
 7 namespace System.Runtime.Serialization
 8 {
 9     // 摘要:
10     //     指定該類型要定義或實現一個數據協定,並可由序列化程序(如 System.Runtime.Serialization.DataContractSerializer)進行序列化。
11     //     若要使其類型可序列化,類型作者必須為其類型定義數據協定。
12     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, Inherited = false, AllowMultiple = false)]
13     public sealed class DataContractAttribute : Attribute
14     {
15         // 摘要:
16         //     初始化 System.Runtime.Serialization.DataContractAttribute 類的新實例。
17         public DataContractAttribute();
18 
19         // 摘要:
20         //     獲取或設置一個值,該值指示是否保留對象引用數據。
21         //
22         // 返回結果:
23         //     如果使用標准 XML 保留對象引用數據,則為 true;否則為 false。 默認值為 false。
24         public bool IsReference { get; set; }
25         //
26         // 摘要:
27         //     獲取或設置類型的數據協定的名稱。
28         //
29         // 返回結果:
30         //     數據協定的本地名稱。 默認值是應用了該屬性的類的名稱。
31         public string Name { get; set; }
32         //
33         // 摘要:
34         //     獲取或設置類型的數據協定的命名空間。
35         //
36         // 返回結果:
37         //     協定的命名空間。
38         public string Namespace { get; set; }
39     }
40 }
DataContractAttribute

      從應用在DataContractAttribute上的AttributeUsageAttribute特性看,該特性只能用於枚舉、類、結構體而不能應用於接口,從關鍵字sealed知道DataContractAttribute是不可被繼承的。AllowMutiple屬性為False,表明一個數據類型上只能應用一個DataContractAttribute特性。

      從上面對DataContractAttribute定義看出DataContractAttribute僅僅包含3個屬性成員,其中Name和Namespace表示數據契約的名稱和命名空間,IsReference表示在進行序列化的時候是否保持對象現有的引用結構,該屬性默認值為False。

       數據契約成員采用顯示選擇機制,也就是說,應用了DataContractAttribute特性的數據類型的屬性/字段不會自動生成契約的數據成員,而只有那些應用了DataMemberAttribute特性的屬性/字段才屬於數據契約的成員。

 1 #region 程序集 System.Runtime.Serialization.dll, v4.0.0.0
 2 // C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Runtime.Serialization.dll
 3 #endregion
 4 
 5 using System;
 6 
 7 namespace System.Runtime.Serialization
 8 {
 9     // 摘要:
10     //     當應用於類型的成員時,指定該成員是數據協定的一部分並可由 System.Runtime.Serialization.DataContractSerializer
11     //     進行序列化。
12     [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
13     public sealed class DataMemberAttribute : Attribute
14     {
15         // 摘要:
16         //     初始化 System.Runtime.Serialization.DataMemberAttribute 類的新實例。
17         public DataMemberAttribute();
18 
19         // 摘要:
20         //     獲取或設置一個值,該值指定是否對正在被序列化的字段或屬性的默認值進行序列化。
21         //
22         // 返回結果:
23         //     如果應該在序列化流中生成成員的默認值,則為 true;否則為 false。 默認值為 true。
24         public bool EmitDefaultValue { get; set; }
25         //
26         // 摘要:
27         //     獲取或設置一個值,該值用於指示序列化引擎在讀取或反序列化時成員必須存在。
28         //
29         // 返回結果:
30         //     如果該成員是必需的,則為 true;否則為 false。
31         //
32         // 異常:
33         //   System.Runtime.Serialization.SerializationException:
34         //     該成員不存在。
35         public bool IsRequired { get; set; }
36         //
37         // 摘要:
38         //     獲取或設置數據成員名稱。
39         //
40         // 返回結果:
41         //     該數據成員的名稱。 默認值是應用該屬性的目標的名稱。
42         public string Name { get; set; }
43         //
44         // 摘要:
45         //     獲取或設置成員的序列化和反序列化的順序。
46         //
47         // 返回結果:
48         //     序列化或反序列化的數字順序。
49         public int Order { get; set; }
50     }
51 }
DataMemberAttribute

      從上面應用在DataMemberAttribute上的AttributeUsageAttribute特性來看,該特性只能應用在字段和屬性上。因為只有這兩種元素才是“數據”成員。4個屬性分別表示如下的含義。

  •  Name:數據成員的名稱,默認為字段或屬性的名稱。
  •  Order:相應的數據成員在最終序列化的XML中出現的位置,Order值越小越考前,默認值為-1.
  • IsRequired:表明屬性成員是否是必須的成員。默認值為false,表明該成員是可以缺省的。
  • EmitDefaultValue :獲取或設置一個值,該值指定是否對正在被序列化的字段或屬性的默認值進行序列化。如果應該在序列化流中生成成員的默認值,則為 true;否則為 false。 默認值為 true。

 實例:

     Person類

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Runtime.Serialization;
 7 namespace DataContractSerializerDemo
 8 {
 9     [DataContract]
10     public class Person
11     {
12         public Person(string name, int age, DateTime bithday)
13         {
14             this.name = name;
15             this.age = age;
16             this.birthday = bithday;
17         }
18         private string name;
19         [DataMember]
20         public string Name
21         {
22             get { return name; }
23             set { name = value; }
24         }
25         private int age;
26         [DataMember]
27         public int Age
28         {
29             get { return age; }
30             set { age = value; }
31         }
32         private DateTime birthday;
33         [DataMember]
34         public DateTime Birthday
35         {
36             get { return birthday; }
37             set { birthday = value; }
38         }
39     }
40 }
Person

    Women類(Person類的子類)

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Runtime.Serialization;
 7 namespace DataContractSerializerDemo
 8 {
 9     [DataContract]
10     public class Women : Person
11     {
12         public Women(string name, int age, DateTime birthday, string bwh, string bra)
13             : base(name, age, birthday)
14         {
15             BWH = bwh;
16             Bra = bra;
17         }
18         /// <summary>
19         /// 罩杯
20         /// </summary>
21         [DataMember]
22         public string BWH { get; set; }
23         /// <summary>
24         /// 罩顏色
25         /// </summary>
26         public string Bra { get; set; }
27     }
28 }

    控制台程序:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Runtime.Serialization;
 7 using System.Xml;
 8 namespace DataContractSerializerDemo
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             Person p = new Person("wolfy", 24, Convert.ToDateTime("1989-04-11"));
15             Women w = new Women("蒼老師",40,Convert.ToDateTime("1960-01-01"),"D罩杯","黑色蕾絲");
16             Serialize<Person>(p, "p.xml");
17             Serialize<Women>(w,"w.xml");
18             Console.Read();
19 
20         }
21         /// <summary>
22         /// 序列化輔助方法
23         /// </summary>
24         /// <typeparam name="T"></typeparam>
25         /// <param name="instance"></param>
26         /// <param name="fileName"></param>
27         static void Serialize<T>(T instance, string fileName)
28         {
29             DataContractSerializer serializer = new DataContractSerializer(typeof(T));
30             using (XmlWriter writer = new XmlTextWriter(fileName,Encoding.UTF8))
31             {
32                 serializer.WriteObject(writer, instance);
33             }
34         }
35     }
36 }

 

    最后生成的xml文件:p.xml

1 <Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DataContractSerializerDemo"><Age>24</Age><Birthday>1989-04-11T00:00:00</Birthday><Name>wolfy</Name></Person>

   w.xml

1 <Women xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DataContractSerializerDemo"><Age>40</Age><Birthday>1960-01-01T00:00:00</Birthday><Name>蒼老師</Name><BWH>D罩杯</BWH></Women>

 

  將數據契約與最終生成的XML結構進行對比,我們可以看出DataContractSerializer在默認的情況下采用了如下的序列化規則。

  • XML的根節點名稱為數據契約類型的名稱(這里為Person),默認的命名空間采用的格式為 http://schemas.datacontract.org/2004/07/DataContractSerializerDemo(數據契約類型的命名空間)。
  • 只有顯示地應用了DataMemberAttributue特性的字段或屬性才能作為數據成員參與序列化。
  • 所有數據成員均以XML元素的形式被序列化。
  • 序列化后數據成員在XML中的次序采用這樣的規則:父類數據成員在前,子類數據成員在后;定義在同一個類型中的數據成員按照字母排序。

      如果默認序列化后的xml結構不能滿足我們的需求,則可以通過DataContractAttribute和DataMenmberAttribute這兩個特性對其進行修正。在下面我們通過DataContractAttribute特性設置了數據契約的名稱和命名空間,通過DataMenmberAttribute特性的Name屬性為Name和Birthday兩個屬性設置不同於屬性名稱的數據成員名稱,並通過Order控制數據成員的先后次序。

     修改后的Person類為:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Runtime.Serialization;
 7 namespace DataContractSerializerDemo
 8 {
 9     [DataContract(Namespace="http://www.wolfy.com/")]
10     public class Person
11     {
12         public Person(string name, int age, DateTime bithday)
13         {
14             this.name = name;
15             this.age = age;
16             this.birthday = bithday;
17         }
18         private string name;
19         [DataMember(Name="FirstName",Order=3)]
20         public string Name
21         {
22             get { return name; }
23             set { name = value; }
24         }
25         private int age;
26         [DataMember]
27         public int Age
28         {
29             get { return age; }
30             set { age = value; }
31         }
32         private DateTime birthday;
33         [DataMember(Name="生日",Order=1)]
34         public DateTime Birthday
35         {
36             get { return birthday; }
37             set { birthday = value; }
38         }
39     }
40 }

     再次運行程序,得到如下一個表示序列化的Person對象的XML結構:

<Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.wolfy.com/"><Age>24</Age><生日>1989-04-11T00:00:00</生日><FirstName>wolfy</FirstName></Person>

     有關序列化的方方面面還有很多,這里就把經常用到介紹到這里。

     反序列化輔助方法:

 1  static T DeSerialize<T>(string fileName)
 2         {
 3             DataContractSerializer serializer = new DataContractSerializer(typeof(T));
 4             using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
 5             {
 6                 using (XmlReader reader = new XmlTextReader(fileName, fs))
 7                 {
 8                     return (T)serializer.ReadObject(reader);
 9                 }
10             }
11 
12         }

     運行結果為:

      從反序列化的結果也從側面印證了:只有顯示地應用了DataMemberAttributue特性的字段或屬性才能作為數據成員參與序列化。這條規則,因為在上面並沒有給bra這個屬性加DataMenmberAttribute這個特性,在生成的xml文件中沒有這個元素。反序列化也不會出現這個。

       上篇隨筆: 序列化和反序列化的幾種方式(JavaScriptSerializer 、XmlSerializer、DataContractSerializer)(一)

       參考文獻:

             MSDN:http://msdn.microsoft.com/library/system.runtime.serialization.datacontractserializer.aspx

             《WCF全面解析 上》 蔣金楠 著

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM