序列化和反序列化的几种方式(DataContractSerializer)

DataContractSerializer 

使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档。 无法继承此类。

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

备注

使用 DataContractSerializer 类可以将类型实例序列化和反序列化为 XML 流或文档。 通过将 DataContractAttribute 特性应用于类,而将DataMemberAttribute 特性应用于类成员,可以指定要序列化的属性和字段。

从字面意思来理解就是:数据契约序列化,本文主要是讲解用DataContractSerializer 序列化和反序列化,关于它在WCF中的应用大家可以参考《WCF全面解析上册 蒋金楠著》第五章 序列化,里面有专门的介绍。

DataContractAttribute与DataMenmberAttribute

 DataContractAttribute
#region 程序集 System.Runtime.Serialization.dll, v4.0.0.0
// C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Runtime.Serialization.dll
#endregion
using System;
namespace System.Runtime.Serialization
{
// 摘要:
// 指定该类型要定义或实现一个数据协定,并可由序列化程序(如 System.Runtime.Serialization.DataContractSerializer)进行序列化。
// 若要使其类型可序列化,类型作者必须为其类型定义数据协定。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, Inherited = false, AllowMultiple = false)]
public sealed class DataContractAttribute : Attribute
{
// 摘要:
// 初始化 System.Runtime.Serialization.DataContractAttribute 类的新实例。
public DataContractAttribute();
// 摘要:
// 获取或设置一个值,该值指示是否保留对象引用数据。
//
// 返回结果:
// 如果使用标准 XML 保留对象引用数据,则为 true;否则为 false。 默认值为 false。
public bool IsReference { get; set; }
//
// 摘要:
// 获取或设置类型的数据协定的名称。
//
// 返回结果:
// 数据协定的本地名称。 默认值是应用了该属性的类的名称。
public string Name { get; set; }
//
// 摘要:
// 获取或设置类型的数据协定的命名空间。
//
// 返回结果:
// 协定的命名空间。
public string Namespace { get; set; }
}
}
DataContractAttribute

从应用在DataContractAttribute上的AttributeUsageAttribute特性看,该特性只能用于枚举、类、结构体而不能应用于接口,从关键字sealed知道DataContractAttribute是不可被继承的。AllowMutiple属性为False,表明一个数据类型上只能应用一个DataContractAttribute特性。

从上面对DataContractAttribute定义看出DataContractAttribute仅仅包含3个属性成员,其中Name和Namespace表示数据契约的名称和命名空间,IsReference表示在进行序列化的时候是否保持对象现有的引用结构,该属性默认值为False。

数据契约成员采用显示选择机制,也就是说,应用了DataContractAttribute特性的数据类型的属性/字段不会自动生成契约的数据成员,而只有那些应用了DataMemberAttribute特性的属性/字段才属于数据契约的成员。

 DataMemberAttribute
#region 程序集 System.Runtime.Serialization.dll, v4.0.0.0
// C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Runtime.Serialization.dll
#endregion
using System;
namespace System.Runtime.Serialization
{
// 摘要:
// 当应用于类型的成员时,指定该成员是数据协定的一部分并可由 System.Runtime.Serialization.DataContractSerializer
// 进行序列化。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class DataMemberAttribute : Attribute
{
// 摘要:
// 初始化 System.Runtime.Serialization.DataMemberAttribute 类的新实例。
public DataMemberAttribute();
// 摘要:
// 获取或设置一个值,该值指定是否对正在被序列化的字段或属性的默认值进行序列化。
//
// 返回结果:
// 如果应该在序列化流中生成成员的默认值,则为 true;否则为 false。 默认值为 true。
public bool EmitDefaultValue { get; set; }
//
// 摘要:
// 获取或设置一个值,该值用于指示序列化引擎在读取或反序列化时成员必须存在。
//
// 返回结果:
// 如果该成员是必需的,则为 true;否则为 false。
//
// 异常:
// System.Runtime.Serialization.SerializationException:
// 该成员不存在。
public bool IsRequired { get; set; }
//
// 摘要:
// 获取或设置数据成员名称。
//
// 返回结果:
// 该数据成员的名称。 默认值是应用该属性的目标的名称。
public string Name { get; set; }
//
// 摘要:
// 获取或设置成员的序列化和反序列化的顺序。
//
// 返回结果:
// 序列化或反序列化的数字顺序。
public int Order { get; set; }
}
}
DataMemberAttribute

从上面应用在DataMemberAttribute上的AttributeUsageAttribute特性来看,该特性只能应用在字段和属性上。因为只有这两种元素才是“数据”成员。4个属性分别表示如下的含义。

  • Name:数据成员的名称,默认为字段或属性的名称。
  • Order:相应的数据成员在最终序列化的XML中出现的位置,Order值越小越考前,默认值为-1.
  • IsRequired:表明属性成员是否是必须的成员。默认值为false,表明该成员是可以缺省的。
  • EmitDefaultValue :获取或设置一个值,该值指定是否对正在被序列化的字段或属性的默认值进行序列化。如果应该在序列化流中生成成员的默认值,则为 true;否则为 false。 默认值为 true。

 实例:

     Person类

 Person
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace DataContractSerializerDemo
{
[DataContract]
public class Person
{
public Person(string name, int age, DateTime bithday)
{
this.name = name;
this.age = age;
this.birthday = bithday;
}
private string name;
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
private int age;
[DataMember]
public int Age
{
get { return age; }
set { age = value; }
}
private DateTime birthday;
[DataMember]
public DateTime Birthday
{
get { return birthday; }
set { birthday = value; }
}
}
}
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全面解析 上》 蒋金楠 著

 
 
分类: C#WCF

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

  1. 序列化和反序列化的几种方式(DataContractSerializer)(二)

    DataContractSerializer 类 使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档. 无法继承此类. 命名空间: System.Runtime.Serializati ...

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

    JavaScriptSerializer 类 为启用 AJAX 的应用程序提供序列化和反序列化功能. 命名空间:   System.Web.Script.Serialization 程序集:  Sys ...

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

    在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象. 什么是JSON? JSON (JavaScript Object Notation) ...

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

    转载自  https://www.cnblogs.com/caofangsheng/p/5687994.html    谢谢 在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据 ...

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

    在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象. 什么是JSON? JSON (JavaScript Object Notation) ...

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

    摘自:http://www.cnblogs.com/caofangsheng/p/5687994.html 在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化 ...

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

    一.什么是JSON JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于ECMAScript(欧洲计算机协会制定的js规范)的一个子集 ...

  8. Json 序列化以及反序列化的三种方式(二)

    1.什么是JSON? Json[javascript对象表示方法],它是一个轻量级的数据交换格式,我们可以很简单的来读取和写它,并且它很容易被计算机转化和生成,它是完全独立于语言的 2.Json支持下 ...

  9. golang的序列化与反序列化的几种方式

    golang用来序列化的模块有很多,我们来介绍3个. json 首先登场的是json,这个几乎毋庸置疑. 序列化 package main import ( "encoding/json&q ...

随机推荐

  1. Session与Caching

    Session与Caching 在之前的版本中,Session存在于System.Web中,新版ASP.NET 5中由于不在依赖于System.Web.dll库了,所以相应的,Session也就成了A ...

  2. linux_coom _ Linux文件比较,文本文件的交集、差集与求差

    交集和差集操作在集合论相关的数学课上经常用到,不过,在Linux下 对文本进行类似的操作在某些情况下也很有用. comm命令 comm命令可以用于两个文件之间的 比较,它有一些选项可以用来调整输出,以 ...

  3. android之【本地通知Notification】

    public class NotificationTest extends Activity { static final int NOTIFICATION_ID = 0x1123; @Overrid ...

  4. net.sf.json 迄今 时刻 格式 办法

    创作工具类 import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import  ...

  5. Swift入门教程:基本语法(二)

    数字格式 数字可以增加额外的格式,使它们更容易阅读 可以增加额外的零 0 let money = 001999           // 1999 let money2 = 001999.000   ...

  6. c#之函数创建和闭包

    c#之函数创建和闭包 阅读目录: 动态创建函数 匿名函数不足之处 理解c#中的闭包 闭包的优点 动态创建函数 大多数同学,都或多或少的使用过.回顾下c#中动态创建函数的进化: C# 1.0中: pub ...

  7. 多种语言socket编程集锦—win32

    原文 http://www.blogjava.net/huyi2006/articles/263831.html 借此地方整理以下socket编程的多种语言的实现,socket可以跨平台的通信,因此多 ...

  8. TRS_WCM(拓尔思信息技术有限公司)内容协作平台平台置标经验攻略

    TRS_WCM置标过程中经验积累 版本V4.0-2014.6.24-穿越者7号 目录 1.嵌套模板置标 1 2.栏目名称超链接置标 1 3.列表循环输出文档标题包含超链接 1 4.取既定栏目下第一篇文 ...

  9. JavaScript继承基础讲解,原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承

    说好的讲解JavaScript继承,可是迟迟到现在讲解.废话不多说,直接进入正题. 既然你想了解继承,证明你对JavaScript面向对象已经有一定的了解,如还有什么不理解的可以参考<面向对象J ...

  10. 腾讯QQ音乐网页版 音频初始化模块解压混淆js源码

    define("js/view/playerBar.js",function(t,e,o){ var i = t("js/lib/zepto.js"), a = ...