WCF揭秘学习笔记(2):数据表示
背景知识
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):数据表示的更多相关文章
- WCF揭秘学习笔记(1):基础知识
最近找工作,面试时经常被问懂不懂WCF.不少招聘高级.NET工程师的要求上都 写着有WCF开发经验的优先考虑.我对于WCF仅仅是通过看一些教学视频这种山寨学习法了解一些.现在要下决心好好学习一下WCF ...
- WCF揭秘学习笔记(5):WF定制活动
WF(Windows Workflow Foundation,Windows工作流基础)为.NET提供了一种基于模型的.声明方式的过程执行引擎,它改变了传统的通过一行行编写代码来开发服务功能的方式. ...
- WCF揭秘学习笔记(4):可信赖会话、会话管理、队列、事务
可信赖会话 WCF的可信赖会话在绑定层保证消息只会被传输一次,并且保证消息间的顺序.当使用TCP通信时,协议本身保证了可靠性,但它只在两点间的网络 包这个层面提供了这样的保证.WCF的可信赖会话特性保 ...
- WCF揭秘学习笔记(3):使用DataContractSerializer
使用DataContractSerializer 终结点(包括地址.绑定.契约)可通过代码以编程方式添加到服务中.如: using(ServiceHost host =new ServiceHost( ...
- WCF双工学习笔记
WCF双工的作用在于服务端执行某个方法的时候调用客户端的方法,有点类似委托的感觉,实际项目中在什么情况下使用还没想到. WCF双工支持两种bind,一是nettcp.另一个是wsDualHttp,这里 ...
- ASP.NET MVC5框架揭秘 学习笔记01
1.自治视图 在早期(作者也没说明是多早,自己猜吧),我们倾向于将所有与UI相关的操作糅合在一起(现在我身边还有很多人这样做),这些操作包括UI界面的呈现. 用户交互操作的捕捉与响应(UI处理逻辑). ...
- Dynamic CRM 2013学习笔记(二十二)插件里调用WCF服务
1. 添加service: 2.调用WCF BasicHttpBinding myBinding = new BasicHttpBinding(); myBinding.Name = &q ...
- WCF学习笔记之事务编程
WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...
- WCF学习笔记之传输安全
WCF学习笔记之传输安全 最近学习[WCF全面解析]下册的知识,针对传输安全的内容做一个简单的记录,这边只是简单的记录一些要点:本文的内容均来自[WCF全面解析]下册: WCF的传输安全主要涉及认证. ...
随机推荐
- 20145309 李昊 《网络攻防》 Exp2 后门原理与实践
实践内容: (1)理解免杀技术原理(1分) (2)正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧:(2分) (3)通过组合应用各种技术实现恶意代码免杀( ...
- Java静态内存与动态内存分配的解析
1. 静态内存 静态内存是指在程序开始运行时由编译器分配的内存,它的分配是在程序开始编译时完成的,不占用CPU资源. 程序中的各种变量,在编译时系统已经为其分配了所需的内存空间,当该变量在作用域内使用 ...
- 数据导入(二):MapReduce
package test091201; import java.io.IOException; import java.text.SimpleDateFormat; import java.util. ...
- 分布式之zk的应用场景
分布式应用系统中,经常会用到zk,比如dubbo注册中心,kafka分布式集群等都用到zk这一工具.除了这些用来做分布式集群外,zk还有那西应用场景事我们可以使用到该工具的呢?所以接下来就是我们要了解 ...
- session放数据库里解决丢失的问题
在编程里是会话的意思Session 对象存储特定用户会话所需的信息.这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去. ...
- 从invalidAuthenticationToken❌想到需要忽略:verify_authenticity_token。
https://www.cnblogs.com/chentianwei/diary/2018/07/11/9296126.html 这篇日记记录了我遇到的invalidAuthenticaitonTo ...
- 如何高效利用 GitHub
正是 Github,让社会化编程成为现实.本文尝试谈谈 GitHub 的文化.技巧与影响. Q1:GitHub 是什么 Q2:GitHub 风格 Q3: 在 GitHub,如何跟牛人学习 Q4: 享受 ...
- HDU1598 并查集+贪心
find the most comfortable road Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ...
- js获取当前日期加上30天之后的日期
var date1 = new Date(); var date2 = new Date(date1); date2.setDate(date1.getDate() + 30); console.lo ...
- PCB 中过孔和通孔焊盘的区别
在PCB设计中,过孔VIA和焊盘PAD都可以实现相似的功能.它们都能插入元件管脚,特别是对于直插DIP)封装的的器件来说,几乎是一样的. 但是!在PCB制造中,它们的处理方法是不一样的. 1.VIA的 ...