序列化和反序列化的几种方式(DataContractSerializer)(二)
DataContractSerializer 类
使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档。 无法继承此类。
命名空间: System.Runtime.Serialization
程序集: System.Runtime.Serialization(在 System.Runtime.Serialization.dll 中)
备注
使用 DataContractSerializer 类可以将类型实例序列化和反序列化为 XML 流或文档。 通过将 DataContractAttribute 特性应用于类,而将DataMemberAttribute 特性应用于类成员,可以指定要序列化的属性和字段。
从字面意思来理解就是:数据契约序列化,本文主要是讲解用DataContractSerializer 序列化和反序列化,关于它在WCF中的应用大家可以参考《WCF全面解析上册 蒋金楠著》第五章 序列化,里面有专门的介绍。
DataContractAttribute与DataMenmberAttribute
![](/assets/blank.gif)
![](/assets/blank.gif)
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特性的属性/字段才属于数据契约的成员。
![](/assets/blank.gif)
![](/assets/blank.gif)
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类
![](/assets/blank.gif)
![](/assets/blank.gif)
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全面解析 上》 蒋金楠 著
转载于:https://www.cnblogs.com/wolf-sun/p/3319976.html
序列化和反序列化的几种方式(DataContractSerializer)(二)相关推荐
- Json 序列化以及反序列化的三种方式(二)
1.什么是JSON? Json[javascript对象表示方法],它是一个轻量级的数据交换格式,我们可以很简单的来读取和写它,并且它很容易被计算机转化和生成,它是完全独立于语言的 2.Json支持下 ...
- 在C#中,Json的序列化和反序列化的几种方式总结
在C#中,Json的序列化和反序列化的几种方式总结 在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象. 什么是JSON? JSON (Ja ...
- 序列化和反序列化的几种方式(JavaScriptSerializer 、XmlSerializer、DataContractSerializer)(一)...
JavaScriptSerializer 类 为启用 AJAX 的应用程序提供序列化和反序列化功能. 命名空间: System.Web.Script.Serialization 程序集: Sys ...
- Json的序列化和反序列化的几种方式
[什么是Json] 序列化:将对象转换成字节流的过程,这样就可以轻松将对象保存在磁盘文件或数据库中. 反序列化:序列化的逆过程,就是将字节流转换回原来的对象的过程. 当前主流的序列化JSON字符串主要 ...
- 二叉树序列化和反序列化的两种方式
介绍 二叉树的序列化和反序列化,有两种方式: 第一种方式在将二叉树序列化为数组的时候,需要标记空指针为特殊符号,这样在反序列化的时候,就可以根据这些符号和序列方式来确定一颗二叉树. 第二种方式在序列化 ...
- Py之qrcode:调用python的qrcode库两种方式生成二维码、带logo的二维码
Py之qrcode:调用python的qrcode库两种方式生成二维码.带logo的二维码 目录 python编程实现生成二维码 1.第一种方式-纯文本 2.第二种方式-带logo
- .NET 实现并行的几种方式(二)
本随笔续接:.NET 实现并行的几种方式(一) 四.Task 3)Task.NET 4.5 中的简易方式 在上篇随笔中,两个Demo使用的是 .NET 4.0 中的方式,代码写起来略显麻烦,这不 .N ...
- Unity编辑器开发——通过模板创建Lua脚本的两种方式(二)
个人学习笔记,如有错误.疑问.建议,欢迎留言. 本文有关代码转载自:Unity3D 扩展编辑器实现创建Lua脚本 - 知乎 (zhihu.com) 声明:本文转载已取得原文章作者同意,有兴趣的可以关注 ...
- .Net序列化与反序列化的2种方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
最新文章
- 深入解析Spring MVC与Web Flow
- 性能超过人类炼丹师,AutoGluon 低调开源
- mysql in 原理_深入理解MySql子查询IN的执行和优化
- 用c语言实现随机无向图的生成,C ++程序为给定数量的边生成随机无向图
- 使用ubuntu过程中遇到的问题汇总
- java多线程之hashmap concurrenthashmap的状态同步
- LeetCode Solutions : Reorder List
- vuejs项目如何修改node_mudule为公用文件?
- c语言生成随机英文字母,菜鸟求助,写一个随机输出26个英文字母的程序
- opencv中Mat与IplImage,CVMat类型之间转换
- 米斯特白帽培训讲义 工具篇 Nmap
- 电大有计算机教程吗,电大教程 计算机概述.ppt
- LINUX 安装护眼软件
- 1.Lunix系统安装及重置root密码
- 相量的瞬时功率 平均功率 无功功率 视在功率
- 抢先体验 Ubuntu 22.04 Jammy Jellyfish
- 连接到mysql提示错误:The server time zone value is unrecognized or represents more than one time zone
- Cocos Creator 新手引导制作
- gulp项目中的package配置说明
- 汇编语言中常用进制数据输出的程序实现