背景知识

  WCF提供了一种语言为软件通信建模,称作服务模型。使用更底层的编程架构提供的类可以从这种语言建立的模型中生成可用的通信软件。

  在服务模型使用的语言中,负责通信的软件部分称为服务(service)。一个服务具有一个或多个通信的终结点,终结点包括地址、绑定和契约。

  地址的作用比较简单,它通过使用URL指定服务的唯一地址。

  绑定指定了客户端与服务器间的通信协议。绑定至少需要分别提供一种编码消息和传输消息的协议。

  契约指定了在一个终结点可以执行的操作。

  以上节中的契约为例:


//契约
[ServiceContract]
publicinterface IDerivativesCalculator
{
[OperationContract]
decimal CalculateDerivative(
string[] symbols,
decimal[] parameters,
string[] functions);
......
} //客户端调用服务代码
string[] symbols =newstring[] {"MSFT"};
decimal[] parameters =newdecimal[]{};
string[] functions =newstring[]{ "TechStockProjections" }; IDerivativesCalculator proxy =new ChannelFactory<IDerivativesCalculator>
("CalculatorEnpoint").CreateChannel();
proxy.CalculateDerivative(symbols, parameters, functions);
((IChannel)proxy).Close();

  当执行代码proxy.CalculateDerivative(symbols, parameters, functions)时,作为输入传给操作的数据会被添加到一个Message类的实例中。Message是WCF信道层提供的一个类。在Message 类里,数据被标识成一个XML信息集(XML Information Set),通常称为InfoSet。当数据准备从客户端传输给服务器端时,绑定里指定的消息编码协议将决定包含客户端所提供数据的Message对象将以 何种形式表示给服务。消息编码协议可能会将消息转换成逗号隔开的字符串值,或JavaScript Object-Notation Format,或任何其他格式。然而,所有标准的绑定都会将Message对象表示成XML InfoSet的编码协议。根据预定义绑定的编码协议,XML InfoSet可能会使用各种标准的XML文本编码格式、标准的MTOM协议或使用WCF自己的二进制格式。

  当WCF服务接收到传输数据时,不管客户端是怎么样的编码格式,消息编码绑定元素会重新将它组装成一个Message对象,客户端发送的数据就 会在Message对象中以XML InfoSet的形式表示。这个Message对象会被传给WCF的调度器(dispatcher)组件。调度器组件从XML InfoSet中抽取出客户端的数据项,然后它会调用服务中实现了客户端所请求的操作的方法,而这些数据将作为方法的参数。

XmlSerializer和DataContractSerializer

  从客户端发给服务的数据会被序列化为XML,然后在服务器端又会从XML反序列化为原始的数据。WCF提供了两种XML序列化的工具来完成这项任务。

  一种就是已包含在.NET Framework类库的System.XML程序集中的System.Xml.Serialization.XmlSerializer。另一种是由 WCF提供的,即在System.Runtime.Ser-ialization程序集中的 System.Runtime.Serialization.DataContractSerializer。后者是Windows默认情况下使用的 XML序列化程序。

  我们可以通过添加System.Runtime.Serialization.DataContract和 System.Runtime.Serialization.DataMember特性使指定类能被 System.Runtime.Serialization.-DataContractSerializer所序列化。通过为类添加 System.Runtime.Serialization.DataContract特性、为类的成员添加 System.Runtime.Serialization.DataMember特性而将一个类的实例以XML表示,在WCF的术语里称为数据契约 (data contract)。


[DataContract]
publicclass DerivativesCalculation
{
[DataMember]
privatestring[] symbols;
[DataMember]
privatedecimal[] parameters;
[DataMember]
privatestring[] functions; publicstring[] Symbols
{
get { returnthis.symbols; }
set { this.symbols = value; }
}
......
}

  虽然DataContractSerializer是WCF默认的XML序列化程序,但通过配置也可使用System.Xml.Serialization.XmlSerializer类进行XML序列化。如下所示:


[ServiceContract]
[XmlSerializerFormat]
publicinterface IDerivativesCalculator
{
[OperationContract]
decimal CalculateDerivative(string[] symbols, decimal[] parameters, string[] functions);
......
}

  也可以只为某个操作指定使用XmlSerializer类作为XML序列化程序:


[ServiceContract]
[XmlSerializerFormat]
publicinterface IDerivativesCalculator
{
[OperationContract]
[XmlSerializerFormat]
decimal CalculateDerivative(string[] symbols, decimal[] parameters, string[] functions);
......
}

  XmlSerializer为如何将数据表示成XML提供了精确控制,而DataContractSerializer在这方面只提供了很少的控制。它只允许指定在XML中用来引用数据的命名空间和名称,及数据项在XML里出现的顺序。如下所示:


[DataContract(Namespace="Derivatives", Name="Calculation")]
publicclass DerivativesCalculation
{
[DataMember(Namespace="Derivatives", Name="Symbols", Order=)]
privatestring[] symbols;
[DataMember(Namespace="Derivatives", Name="Parameters", Order=)]
privatedecimal[] parameters;
......
}

  System.Xml.Serialization.XmlSerializer默认将所有公有数据项都序列化成XML,与此不 同,System.Runtime.Serialization.DataContractSerializer要求通过添加 System.Runtime.Serialization.DataMember显式地指定哪些数据是需要序列化的。

  由于不允许控制数据项如何被序列化表示成XML,对于 System.Runtime.Serialization.DataContractSerializer来说序列化的过程是完全可预知的,从而也更加 容易进行优化。所以DataContratSerializer的一个很实际的好处就是有更好的性能--大概比 System.Xml.Serialization.XmlSerializer提升了10%。

XML物神

  以面向服务编程为主要特征的开发方式通常称为契约优先开发(contract-first development)。契约优先开发在构建软件时,一般会首先为外部接口进行交换的数据结构指定与平台无关的表示方法,以及与平台无关的数据交换协议。

  使用契约优先开发方式可以帮助人们避免这样的错误:本来打算创建一个可以在不同平台间交互的软件,但最后它却使用了只在某个平台上才使用的数据 格式,如.NET DataSet格式。然而,这种开发实践常被一种特别的契约优先方式所混淆,在这种特别的开发方式里,人们特别关注XML格式。这种方式会在编辑器里用 XML Schema语言定义数据格式,并保证最后所有的复杂数据类型都定义成XML Schema的数据类型。这样容易分心把考虑的重点转移到数据在XML里空竟是如何表示的,最后,人们开始争论各种XML编码方式的优点,而且对那些可能 妨碍他们直接看到或接触XML的东西表示怀疑。这样,XML在他们眼里变成一个物神(fetish),错误的认为它是契约优先开发的优点。

  使用System.Runtime.Serialization.DataContractSerializer,WCF不仅将软件开发者的注意力重新拉回到本应为最重要的东西上,而且也将数据表示的控制定位在合适的地方,也就是代码之外,即管理员的工作范围内。

创建服务

  WCF开发者使用System.Runtime.Serialization.DataContract特性和 System.Runtime.Serialization.DataMember特性定义服务需要交换的数据结构,然后他们可以使用第2章介绍的服务元 数据工具将这些数据结构用XML Schema表示。他们将这些XML Schema语言的表示提供给需要使用他们的服务的开发者。WCF的设计者们已经做出很大的努力以保证 System.Runtime.Serialization.DataContractSerializer将数据所序列化的XML结构可被现有的各种第 三方提供的反序列化XML数据的工具读入。

  但是,如果开发者希望限制作为输入的值的有效范围该怎么办呢?XML Schema语言提供了比.NET编程语言更丰富的功能来做这样的限制,而System.Runtime.Serializa- tion.DataContract和System.Runtime.Serialization.DataMember甚至根本没有提供类似的功能。 XML Schema语言不仅可让开发者告诉想使用他们服务的开发者输入值的有效范围,而且还可根据XML Schema定义检查XML表示的输入值是不是越出了有效范围。

  一个可行的办法是对输入值命名时使用一些有意义的名字,如下所示:

[DataContract]
publicclass BookOrderType
{
[DataMember]
publicint QuantityValueBetween100And1000;
}

  然后在代码里检查值的范围,并且在值越界时返回相应的异常。

创建客户端

  如果服务输入和输出数据的XML表示与 System.Runtime.Serialization.DataContractSerializer将数据表示成XML的方式不一致,服务元数据 工具所生成代码里的开关代码会选择使用XmlSerializer而不是DataContractSerializer去将数据序列化成XML。这样的代 码可使WCF开发者不需查看或操纵任何XML就可使用服务了。

  有些人对XML非常感兴趣,总希望看看XML Schema,看看类在XML中是怎么表达的。WCF也提供了满足他们的工具。按下面的方式执行服务元数据工具:

  svcutil /datacontractonly SomeAssembly.dll

  其中SomeAssembly.dll是包含了一个类的数据契约定义的程序集名称。这个命令会生成定义了这个类的实例被序列成的XML的XML Schema。

  现在我们来考虑:DataContractSerializer通过牺牲对数据如何表示成XML的控制,换来性能的改善值得吗?其实控制数据如何表示成XML对于开发者来说通常是没有用的,所以任何通过这种控制换来的性能提升都是受欢迎的。

WCF揭秘学习笔记(2):数据表示的更多相关文章

  1. WCF揭秘学习笔记(1):基础知识

    最近找工作,面试时经常被问懂不懂WCF.不少招聘高级.NET工程师的要求上都 写着有WCF开发经验的优先考虑.我对于WCF仅仅是通过看一些教学视频这种山寨学习法了解一些.现在要下决心好好学习一下WCF ...

  2. WCF揭秘学习笔记(5):WF定制活动

    WF(Windows Workflow Foundation,Windows工作流基础)为.NET提供了一种基于模型的.声明方式的过程执行引擎,它改变了传统的通过一行行编写代码来开发服务功能的方式. ...

  3. WCF揭秘学习笔记(4):可信赖会话、会话管理、队列、事务

    可信赖会话 WCF的可信赖会话在绑定层保证消息只会被传输一次,并且保证消息间的顺序.当使用TCP通信时,协议本身保证了可靠性,但它只在两点间的网络 包这个层面提供了这样的保证.WCF的可信赖会话特性保 ...

  4. WCF揭秘学习笔记(3):使用DataContractSerializer

    使用DataContractSerializer 终结点(包括地址.绑定.契约)可通过代码以编程方式添加到服务中.如: using(ServiceHost host =new ServiceHost( ...

  5. WCF双工学习笔记

    WCF双工的作用在于服务端执行某个方法的时候调用客户端的方法,有点类似委托的感觉,实际项目中在什么情况下使用还没想到. WCF双工支持两种bind,一是nettcp.另一个是wsDualHttp,这里 ...

  6. ASP.NET MVC5框架揭秘 学习笔记01

    1.自治视图 在早期(作者也没说明是多早,自己猜吧),我们倾向于将所有与UI相关的操作糅合在一起(现在我身边还有很多人这样做),这些操作包括UI界面的呈现. 用户交互操作的捕捉与响应(UI处理逻辑). ...

  7. Dynamic CRM 2013学习笔记(二十二)插件里调用WCF服务

      1. 添加service:     2.调用WCF BasicHttpBinding myBinding = new BasicHttpBinding(); myBinding.Name = &q ...

  8. WCF学习笔记之事务编程

    WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...

  9. WCF学习笔记之传输安全

    WCF学习笔记之传输安全 最近学习[WCF全面解析]下册的知识,针对传输安全的内容做一个简单的记录,这边只是简单的记录一些要点:本文的内容均来自[WCF全面解析]下册: WCF的传输安全主要涉及认证. ...

随机推荐

  1. 20145221 《Java程序设计》课程总结

    20145221 <Java程序设计>课程总结 每周读书笔记链接汇总 Atom使用心得 - 21世纪的编辑器 网络安全攻防学习平台 - 基础关 Java实现:数据结构之排序 2014522 ...

  2. 20145326《Java程序设计》第二周学习总结

    20145326<Java程序设计>第二周学习总结 教材学习内容总结 本周学习教材第三章,本章主要讲述了java语言中的一些基础语法,java是个支持面向对象的程序语言,但在正式进入面向对 ...

  3. POJ 1062 昂贵的聘礼(最短路)题解

    题意:中文题意不解释... 思路:交换物品使得费用最小,很明显的最短路,边的权值就是优惠的价格,可以直接用Dijkstra解决.但是题目中要求最短路路径中任意两个等级不能超过m,我们不能在连最短路的时 ...

  4. No module named import_export.admin

    解决方法: pip install django-import-export

  5. Codeforces Round #390 (Div. 2) A. Lesha and array splitting

    http://codeforces.com/contest/754/problem/A 题意: 给出一串序列,现在要把这串序列分成多个序列,使得每一个序列的sum都不为0. 思路: 先统计一下不为0的 ...

  6. Qt570_CentOS64x64_01

    ZC: 其实 主要是要安装 OpenGL,具体看"3"... ... 1.运行 "/opt/Qt5.7.0/Tools/QtCreator/bin/qtcreator&q ...

  7. Android-----------广告图片轮播控件

    Banner广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式.动画.轮播和切换时间.位置.图片加载框架等! 很多Android APP中都有广告栏,我也用过很多次了,特来写一篇博文. 先 ...

  8. Linux命令详解-whatis

    描述一个命令执行什么功能. 1.命令格式: whatis [ -M PathName ] Command ... 2.命令功能: 描述一个命令执行什么功能. 3.命令参数:     -M PathNa ...

  9. C++设计与声明——让接口容易被正确使用

    一个简答易错的例子 class Date { public Date(int month,int day,int year); } 一年后使用这个接口的时候,写了Date d(15,10,2015)或 ...

  10. svn版本管理与上线

    1.1 SVN介绍 1.1.1 什么是SVN(Subversion)? Svn(subversion)是近年来崛起的非常优秀的版本管理工具,与CVS管理工具一样,SVN是一个跨平台的开源的版本控制系统 ...