前言

  • WCF包含很多封装的内部机制,这些是我们在编写程序时不会经常看到的。比如上一篇讲解的Message。这一篇我将讲解WCF的另一种内部机制,WCF的序列化和反序列化。通常我们在编写WCF服务程序的时候,我们并没有手动对WCF的数据传递做序列化和反序列化的操作,这是因为WCF默认通过序列化引擎DataContractSerializer帮我们做了这些操作,使得开发人员只需关注数据对象定义本身(比如数据协定、消息协定),而不必关注数据对象的在WCF传输时的序列化机制。
  • DataContractSerializer 可在 .NET Framework 对象和 XML 之间进行双向转换。在对 .NET Framework 对象进行序列化时,序列化程序了解各种序列化编程模型,包括新的数据协定模型。此序列化程序支持下列类型:
  1. 基元类型(如:整数、字符串和字节数组)以及某些特殊类型(如 XmlElement 和 DateTime),这些特殊类型也被视为基元类型。
  2. 数据协定类型(用 DataContractAttribute 属性标记的类型)。
  3. 用 SerializableAttribute 属性标记的类型,包括实现 ISerializable 接口的类型。
  4. 实现 IXmlSerializable 接口的类型。
  5. 许多常见集合类型,包括许多泛型集合类型。

使用DataContractSerializer序列化和反序列化

  • 对对象进行序列化最基本的方法是将其传递到 WriteObject 方法。该方法有三个重载,每个重载分别用于写入到 Stream、XmlWriter 或 XmlDictionaryWriter。使用 Stream 重载时,输出是采用 UTF-8 编码的 XML。使用 XmlDictionaryWriter 重载时,序列化程序会针对二进制 XML 优化其输出。参考代码如下:
   User user = new User { ID = , Name = "JACK", Age = , Nationality = "CHINA" };
FileStream writer = new FileStream(fileName, FileMode.Create);
DataContractSerializer ser =new DataContractSerializer(typeof(User));
ser.WriteObject(writer, user);
writer.Close();
  • 对对象进行反序列化的最基本的方式是调用 ReadObject 方法重载之一。该方法有三个重载,每个重载分别用于读取 XmlDictionaryReader、XmlReader 或 Stream。请注意,Stream 重载将创建不受任何配额保护的文本 XmlDictionaryReader,此重载仅应用于读取受信任的数据。还请注意,必须将 ReadObject 方法返回的对象强制转换为适当的类型。参考代码如下:
    FileStream fs = new FileStream(fileName,FileMode.Open);
XmlDictionaryReader reader =XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(User));
User deserializedUser =(User)ser.ReadObject(reader, true);

使用DataContractSerializer序列化和反序列化示例如下:

  • 创建一个名称为WcfDataContractSerializer的解决方案,添加一个名称为WcfDataContractSerializer的控制台引用程序。修改Program.cs代码如下:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Xml; namespace WcfDataContractSerializer
{
class Program
{
static void Main(string[] args)
{
try
{
WriteObject("DataContractSerializerExample.xml");
ReadObject("DataContractSerializerExample.xml"); } catch (SerializationException serExc)
{
Console.WriteLine("序列化失败");
Console.WriteLine(serExc.Message);
}
catch (Exception exc)
{
Console.WriteLine(
"序列化操作失败: {0} StackTrace: {1}",
exc.Message, exc.StackTrace);
} finally
{
Console.WriteLine("按 <Enter> 键退出....");
Console.ReadLine();
}
} public static void WriteObject(string fileName)
{
Console.WriteLine("创建User对象并序列化它");
User user = new User { ID = , Name = "JACK", Age = , Nationality = "CHINA" };
FileStream writer = new FileStream(fileName, FileMode.Create);
DataContractSerializer ser =new DataContractSerializer(typeof(User));
ser.WriteObject(writer, user);
writer.Close();
Console.WriteLine("序列化User对象成功,请到程序Bin目录下查看DataContractSerializerExample.xml文件");
} public static void ReadObject(string fileName)
{
Console.WriteLine("反序列化实例对象");
FileStream fs = new FileStream(fileName,FileMode.Open);
XmlDictionaryReader reader =XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(User));
User deserializedUser =(User)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
deserializedUser.ID.ToString(),
deserializedUser.Name.ToString(),
deserializedUser.Age.ToString(),
deserializedUser.Nationality.ToString());
}
} [DataContract]
public class User
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Nationality { get; set; }
}
}
  • 运行程序结果如下:

  

  打开程序Bin目录下的DataContractSerializerExample.xml,显示结果如下:

  

使用DataContractJsonSerializer序列化和反序列化

  • 使用DataContractJsonSerializer可以将对象转化为Json格式,如果你习惯使用Json,那么可以使用该序列化引擎作为对象的传输时的序列化工具。该序列化引擎和DataContractSerializer一样,具有WriteObject和ReadObject方法,具体用法参照示例。
  • 注意:该序列化引擎只会对WCF的消息正文进行Json序列化操作,也就是说总个消息还是基于SOAP的XML格式,只有Body部分变成了JSON字符串。

使用DataContractJsonSerializer序列化和反序列化示例

  • 在先前的解决方案上添加名称为WcfDataContractJsonSerializer的控制台应用程序,修改Program.cs的代码如下:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text; namespace WcfDataContractJsonSerializer
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("创建User对象并序列化它");
User user = new User { ID = , Name = "JACK", Age = , Nationality = "CHINA" };
string jsonString = Serialize<User>(user);
Console.WriteLine(jsonString); Console.WriteLine("反序列化实例对象");
User deserializedUser = Deserialize<User>(jsonString);
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
deserializedUser.ID.ToString(),
deserializedUser.Name.ToString(),
deserializedUser.Age.ToString(),
deserializedUser.Nationality.ToString());
} catch (SerializationException serExc)
{
Console.WriteLine("序列化失败");
Console.WriteLine(serExc.Message);
}
catch (Exception exc)
{
Console.WriteLine(
"序列化操作失败: {0} StackTrace: {1}",
exc.Message, exc.StackTrace);
} finally
{
Console.WriteLine("按 <Enter> 键退出....");
Console.ReadLine();
}
} public static string Serialize<T>(T item)
{
if (item == null) return string.Empty;
var serializer = new DataContractJsonSerializer(item.GetType());
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, item);
var sb = new StringBuilder();
sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
return sb.ToString();
}
} public static T Deserialize<T>(string jsonString)
{
if (string.IsNullOrEmpty(jsonString)) return default(T);
var ser = new DataContractJsonSerializer(typeof(T));
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
T jsonObject = (T)ser.ReadObject(ms);
return jsonObject;
}
}
} [DataContract]
public class User
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Nationality { get; set; }
}
}
  • 运行结果如下:

  

序列化格式大小对比

  • 序列化格式的三种类型:XML文本类型、Json文本类型、二进制类型。接下来,我们通过一个小示例来看看这三种类型序列化时的字节大小。因为我们知道在网络数据传输时,字节大小的传递显得尤为重要呢。
  • 在先前的解决方案中添加名称为WcfSerializerCompare的控制台应用程序,修改Program.cs的代码如下:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Xml; namespace WcfSerializerCompare
{
class Program
{
static void Main(string[] args)
{
MemoryStream stream1 = new MemoryStream();
MemoryStream stream2 = new MemoryStream();
MemoryStream stream3 = new MemoryStream();
User user = new User { ID = , Name = "JACK", Age = , Nationality = "CHINA" }; DataContractSerializer xmlSerializer = new DataContractSerializer(typeof(User));
xmlSerializer.WriteObject(stream1, user); DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(User));
jsonSerializer.WriteObject(stream2, user); DataContractSerializer binarySerializer = new DataContractSerializer(typeof(User));
XmlDictionaryWriter write = XmlDictionaryWriter.CreateBinaryWriter(stream3);
binarySerializer.WriteObject(write, user);
write.Flush(); Console.WriteLine("XML文本字节数大小为:{0}bytes", stream1.Length);
Console.WriteLine("JSON文本字节数大小为:{0}bytes", stream2.Length);
Console.WriteLine("二进制字节数大小为:{0}bytes", stream3.Length); Console.Read(); }
} [DataContract]
public class User
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Nationality { get; set; }
}
}
  • 运行结果如下:

  

  从上面的示例可以看出,采用Json文本传输的格式为最小,只有53个字节数。

WCF初探-24:WCF序列化和反序列化的更多相关文章

  1. WCF初探文章列表

    WCF初探-1:认识WCF WCF初探-6:WCF服务配置 WCF初探-2:手动实现WCF程序 WCF初探-7:WCF服务配置工具使用 WCF初探-3:WCF消息交换模式之单向模式 WCF初探-8:W ...

  2. 对 JSON 数据进行序列化和反序列化

    如何:对 JSON 数据进行序列化和反序列化 2017/03/30 作者 JSON(JavaScript 对象符号)是一种高效的数据编码格式,可用于在客户端浏览器和支持 AJAX 的 Web 服务之间 ...

  3. 序列化和反序列化,异步调用web/wcf/函数

    //xml序列化 public static string Seria(DataSet ds) { XmlSerializer serializer = new XmlSerializer(typeo ...

  4. WCF序列化与反序列化问题

    转自:http://www.cnblogs.com/wangweimutou/p/4505447.html WCF包含很多封装的内部机制,这些是我们在编写程序时不会经常看到的.比如上一篇讲解的Mess ...

  5. WCF初探-20:WCF错误协定

    WCF错误协定概述 在所有托管应用程序中,处理错误由 Exception 对象表示. 在基于 SOAP 的应用程序(如 WCF 应用程序)中,服务方法使用 SOAP 错误消息来传递处理错误信息. SO ...

  6. WCF初探-25:WCF中使用XmlSerializer类

    前言 在上一篇WCF序列化和反序列化中,文章介绍了WCF序列化和反序列化的机制,虽然WCF针对序列化提供了默认的DataContractSerializer序列化引擎,但是WCF还支持其他的序列化引擎 ...

  7. WCF初探-16:WCF数据协定之基础知识

    数据协定概念 “数据协定”是在服务与客户端之间达成的正式协议,用于以抽象方式描述要交换的数据. 也就是说,为了进行通信,客户端和服务不必共享相同的类型,而只需共享相同的数据协定. 数据协定为每一个做数 ...

  8. WCF初探-22:WCF中使用Message类(上)

    前言 从我们学习WCF以来,就一直强调WCF是基于消息的通信机制.但是由于WCF给我们做了高级封装,以至于我们在使用WCF的时候很少了解到消息的内部机制.由于WCF的架构的可扩展性,针对一些特殊情况, ...

  9. 跟我一起学WCF(7)——WCF数据契约与序列化详解

    一.引言 在前面博文介绍到,WCF的契约包括操作契约.数据契约.消息契约和错误契约,前面一篇博文已经结束了操作契约的介绍,接下来自然就是介绍数据契约了.所以本文要分享的内容就是数据契约. 二.数据契约 ...

随机推荐

  1. Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead

    Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead 在解决问题Underscores can only ...

  2. 使用ajax上传中遇到的问题

    使用ajaxSubmit提交文件时,正确使用返回的json数据需要用eval在转化一下. 前台文件: $("#form1").ajaxSubmit({ url: 'QueryHan ...

  3. POJ - 1978 Hanafuda Shuffle

    最初给牌编号时,编号的顺序是从下到上:洗牌时,认牌的顺序是从上到下.注意使用循环是尽量统一“i”的初始化值,都为“0”或者都为“1”,限界条件统一使用“<”或者“<=”. POJ - 19 ...

  4. org.apache.hadoop.security.AccessControlException: Permission denied:

    org.apache.hadoop.security.AccessControlException: Permission denied: user=xxj, access=WRITE, inode= ...

  5. HTML5、CSS3响应式设计——笔记

    1.1.响应式网页设计 响应式网页设计(RWD,Responsive Web Design)这个术语,由伊桑·马科特(EthanMarcotte)提出.他在A List Apart 发表了一篇开创性的 ...

  6. es5.0安装问题

    ES的5.0版本听说在性能上大大优化,于是老大说准备换5.0版本.由于在技术群看到很多人都说ES 5.0 安装有问题,在这里贴出自己在使用最新版5.0遇到的问题和解决方法 1.Elasticsearc ...

  7. SIP协议栈基础笔记

    //------------------SIP基础------------------------// SIP是基于UDP的协议 UA(user Agent)用户代理 UAC(client)发起SIP ...

  8. html与jsp

    1. 什么是 HTML 语言? HTML文件有什么特征? 答:HTML是超文本标记语言(Hypertext Mark-up Language)的缩写,主要用来创建与系统平台无关的网页文档.它是目前网络 ...

  9. CentOS 7下关于systemd的一些唠叨话一:systemd的特点和使用

    摘要 近年来,Linux 系统的 init 进程经历了两次重大的演进,传统的 sysvinit 已经逐渐淡出历史舞台,新的 UpStart 和 systemd 各有特点,越来越多的 Linux 发行版 ...

  10. OpenCV安装配置的简单记录

    在ubuntu16.04下安装OpenCV 2.4.11的简单记录 1. 安装cmake,执行$apt-get install cmake即可,cmake -version验证 2. 下载OpenCV ...