序列化和反序列化的几种方式(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)(一)

时间: 2024-08-07 14:22:16

序列化和反序列化的几种方式(DataContractSerializer)(二)的相关文章

序列化和反序列化的几种方式(JavaScriptSerializer 、XmlSerializer、DataContractSerializer)(一)

JavaScriptSerializer 类 为启用 AJAX 的应用程序提供序列化和反序列化功能. 命名空间: System.Web.Script.Serialization 程序集: System.Web.Extensions(在 System.Web.Extensions.dll 中) JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据. 您无法访问序列化程序的此实例. 但是,此类公开了公共 API. 因此,当您希

C#中,Json的序列化和反序列化的几种方式总结

什么是JSON? JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write and easy for machines to parse and generate. JSON is a text format that is completely language independent. 翻译:Json[javascrip

在C#中,Json的序列化和反序列化的几种方式总结

在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象. 首先,解释一下json Json[javascript对象表示方法],它是一个轻量级的数据交换格式,我们可以很简单的来读取和写它,并且它很容易被计算机转化和生成,它是完全独立于语言的. Json支持下面两种数据结构: 键值对的集合--各种不同的编程语言,都支持这种数据结构: 有序的列表类型值的集合--这其中包含数组,集合,矢量,或者序列,等等. Json有下面几种表现形式 1.对象

.NET中JSON的序列化和反序列化的几种方式

一.什么是JSON JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据.简洁和清晰的层次结构使得JSON 成为理想的数据交换语言. 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率. 是JavaScript用来处理数据的一种格式,大部分是用来处理JavaScript和web服务器端之间的数据交换

序列化和反序列化及线程实现方式

一.序列化与反序列化       把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 序列化关键代码如下: 定义Person类实现序列化.重写toString方法,定义无参以及带参构造 定义类 public class MySerialize { public static void main(String[] args)

.NET 实现并行的几种方式(二)

本随笔续接:.NET 实现并行的几种方式(一) 四.Task 3)Task.NET 4.5 中的简易方式 在上篇随笔中,两个Demo使用的是 .NET 4.0 中的方式,代码写起来略显麻烦,这不 .NET 4.5提供了更加简洁的方式,让我们来看一下吧. /// <summary> /// Task.NET 4.5 中的简易方式 /// </summary> public void Demo3() { Task.Run(() => { SetTip("简洁的代码&qu

Android——数据存储(四种方式之二)读写SD卡

Android--数据存储(四种方式) 1.SharedPrefereces 只能保存一些简单的数轻量级.XML  存储文件名, 数据保存在data/data/basepackage/shared_prefs/myopt.xml中    实例-收藏-记住密码自动登录 //一种轻量级的数据存储方式//通过KEY 存入数据--putxxxx(key,value) 取出数据--getxxxx(key  default) 2.读写SD卡  SD的根目录  适用于数据流读写 实现步骤:加入读写SD卡权限

HBase连接的几种方式(二)

1. HBase连接的方式概况 主要分为: 纯Java API连接HBase的方式: Spark连接HBase的方式: Flink连接HBase的方式: HBase通过Phoenix连接的方式: 第一种方式是HBase自身提供的比较原始的高效操作方式,而第二.第三则分别是Spark.Flink集成HBase的方式,最后一种是第三方插件Phoenix集成的JDBC方式,Phoenix集成的JDBC操作方式也能在Spark.Flink中调用. 注意: 这里我们使用HBase2.1.2版本,以下代码都

Android——数据存储(四种方式之二)读写SD卡——练习

1保存到SDK  --字符串方式 <span style="font-size:18px;"><strong>package com.example.jreduch08.SDK; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.