WCF分布式开发步步为赢(7):WCF数据契约与序列化2011-02-15 博客园 Frank Xu Lei本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤。那么序列化是什么?为什么会有序列化机制?或者说它是为了解决什么问题?作用是什么?现有的.NET 序列化机制和WCF序列化机制有什么不同?我们在本节文章里都会详细介绍。本节结构:【0】数据契约【1】序列化基本概念【2】.NET 序列化机制【3】WCF序列化机制【4】代码实现与分析【5】总结。下面我们正式进入今天的学习阶段,首先来介绍一下数据契约的概念:【0】数据契约(DataContract):在WCF服务编程中我们知道,服务契约定义了远程访问对象和可供调用的服务操作方法,数据契约则是定义服务端和客户端之间要传送的自定义数据类型。在WCF项目中,声明一个类型为DataContract,那么该类型就可以被序列化在服务端和客户端之间传送。类只有声明为DataContract,该类型的对象才可以被传送,且只有类的属性会被传送,需要在属性生命前加DataMember声明,这样该属性就可以被序列化传送。默认情况属性是不可传递的。类的方法不会被传送。WCF对定义的数据契约的类型可以进行更加细节的控制,可以把一个成员属性排除在序列化范围以外,客户端程序不会获得被排除在外的成员属性的任何信息,包括定义和数据。代码如下:
[DataContract]//数据契约属性声明
class MyDataContract
{
[DataMember(Name = "MyName")]//数据成员标记,支持别名定义
public string Name
{
get;
set;
}
[DataMember(Name = "MyEmail")]//数据成员标记,支持别名定义
public string Email
{
get;
set;
}
[DataMember]//数据成员标记
public string Mobile
{
get;
set;
}
//没有[DataMember]声明,不会被序列化
public string Address
{
get;
set;
}
}
}
上面类声明为DataContract,部分属性声明为DataMember(数据成员)。可以序列化为客户端传送。Address成员属性没有被声明为DataMember,因此在交换数据时,不会传输Address的任何信息。声明为DataMember的成员也可以自定义客户端可见的别名 如:[DataMember(Name = "MyName")]//数据成员标记,支持别名定义。【1】序列化基本概念:知道数据契约的一些概念和特性之后,下面来介绍一下序列化的概念。【1.1】为什么序列化:我们这里先来介绍一下为什么需要序列化。当然这个不是必须的。只是针对特定的开发平台的数据或者信息类型而言,当一个系统或者说平台需要和别的异构的系统或者平台交互的时候,两个系统需要一个特定的公开的可以公用的行业标准来支持这个数据信息的交互。这里目前来说支持这个数据交互传递的语言载体就是XML.同样WCF作为面向服务的编程框架,它的目标或者特性之一就是实现服务的跨语言、平台,与不同的服务进行信息数据的交互,而不限制客户端的系统或者开发语言。要实现这个目标,WCF服务首先就是要面对信息的传递与共享问题。我们知道WCF服务和客户端可以传递如Int、String等.NET数据类型。但是如何实现用户自定义复杂类型的跨服务边界的传递,这是一个关键问题。数据契约可以发布为服务的元数据,允许客户端转化为本地语言表示。解决的办法就是封送(Marshaling),将对象封送到其它平台。基于WCF的客户端和服务端参数传递的过程如下图:

主要步骤:客户端序列化参数为XML信息集--传递->服务端反序列化为本地类型--执行结果->序列化结果为XML信息集--传递->客户端序反序列化返回信息为本地类型。在WCF分布式开发必备知识(2):.Net Remoting一节中也介绍了.Net Remoting的通信过程 ,两者也有流程也有部分相似之处。对象封送的概念其实.Net Remoting早有涉及,远程对象(RemoteOject),也就是我们远程要访问的对象.首先定义一个Class,继承MarshalByRefObject,可以使用在remoting应用中,支持对象的跨域边界访问。看过.Net Remoting这节文章应该还有点印象,不同之处是WCF的对象封送是为跨越服务边界,.Net Remoting的封送是为了跨越跨域边界。相关的概念请查阅WCF分布式开发必备知识(2):.Net Remoting或者MSDN,都能找到详细的介绍,这里不在详述。