博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
序列化和反序列化的几种方式(DataContractSerializer)(二)
阅读量:5809 次
发布时间:2019-06-18

本文共 10032 字,大约阅读时间需要 33 分钟。

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 : Attribute14     {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上的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.DataContractSerializer11     //     进行序列化。12     [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]13     public sealed class DataMemberAttribute : Attribute14     {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上的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 Person11     {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 Name21         {22             get { return name; }23             set { name = value; }24         }25         private int age;26         [DataMember]27         public int Age28         {29             get { return age; }30             set { age = value; }31         }32         private DateTime birthday;33         [DataMember]34         public DateTime Birthday35         {36             get { return birthday; }37             set { birthday = value; }38         }39     }40 }

    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 : Person11     {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         /// 19         /// 罩杯20         /// 21         [DataMember]22         public string BWH { get; set; }23         /// 24         /// 罩颜色25         /// 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 Program11     {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
(p, "p.xml");17 Serialize
(w,"w.xml");18 Console.Read();19 20 }21 ///
22 /// 序列化辅助方法23 /// 24 ///
25 ///
26 ///
27 static void Serialize
(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 
24
1989-04-11T00:00:00
wolfy

   w.xml

1 
40
1960-01-01T00:00:00
苍老师
D罩杯

 

  将数据契约与最终生成的XML结构进行对比,我们可以看出DataContractSerializer在默认的情况下采用了如下的序列化规则。

  • XML的根节点名称为数据契约类型的名称(这里为Person),默认的命名空间采用的格式为 (数据契约类型的命名空间)。
  • 只有显示地应用了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 Person11     {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 Name21         {22             get { return name; }23             set { name = value; }24         }25         private int age;26         [DataMember]27         public int Age28         {29             get { return age; }30             set { age = value; }31         }32         private DateTime birthday;33         [DataMember(Name="生日",Order=1)]34         public DateTime Birthday35         {36             get { return birthday; }37             set { birthday = value; }38         }39     }40 }

     再次运行程序,得到如下一个表示序列化的Person对象的XML结构:

24
<生日>
1989-04-11T00:00:00
wolfy

     有关序列化的方方面面还有很多,这里就把经常用到介绍到这里。

     反序列化辅助方法:

1  static T DeSerialize
(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文件中没有这个元素。反序列化也不会出现这个。

       上篇随笔: 

       原文:http://www.cnblogs.com/wolf-sun/p/3319976.html

       参考文献:

             MSDN:

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

 

博客地址:
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。
 
分类:  , 

转载于:https://www.cnblogs.com/qingfang/p/5690622.html

你可能感兴趣的文章
华为3026c交换机配置tftp备份命令
查看>>
Oracle命令导入dmp文件
查看>>
OCP读书笔记(24) - 题库(ExamD)
查看>>
Http、TCP/IP协议与Socket之间的区别(转载)
查看>>
解决Unable to load R3 module ...VBoxDD.dll (VBoxDD):GetLastError=1790
查看>>
.net excel利用NPOI导入oracle
查看>>
vrpie在Visio Studio 中无法调试的问题
查看>>
第六课:数据库的基本工具
查看>>
关于二叉树重构的思索
查看>>
$_SERVER['SCRIPT_FLENAME']与__FILE__
查看>>
skynet实践(8)-接入websocket
查看>>
系统版本判断
查看>>
My97DatePicker 日历插件
查看>>
0603 学术诚信与职业道德
查看>>
小点心家族第3位成员——楼层定位效果
查看>>
Knockout.Js官网学习(enable绑定、disable绑定)
查看>>
hive基本操作与应用
查看>>
excel快捷键设置
查看>>
poj3692
查看>>
python之信号量【Semaphore】
查看>>