WCF之数据契约
- 从抽象层面看,WCF能够托管CLR类型(接口和类)并将它们公开为服务,也能够以本地CLR接口和类的方式使用服务。然而,CLR类型却属于.NET的特定技术。由于面向服务的一个核心原则就是在跨越服务边界时,服务不能够暴露它们的实现技术。因此,不管客户端采用了何种技术,它都能够与服务交互。使用基于XML的样式或信息集(Infoset)实现CLR数据类型与标准的与平台无关的表示形式之间的转换。此外,服务需要一种正式的方法声明两者之间的转换,这就是契约.
- Serializable所指代的涵义是类型的所有成员都是可序列化的,这些成员是组成类型数据样式的一部分。
- 然而,更好的方式是能够提供一种明确参与(Opt-In)途径,只有那些契约的开发者明确包含的成员才应该放到数据契约中。
- Serializable特性强制要求数据类型是可序列化的,从而使得类型可以被用作契约操作的参数,但它却无法实现类型的服务特性(具有成为WCF操作参数的能力)与序列化能力之间的职责分离。
- Serializalbe特性不支持类型名和成员名的别名,也无法将一个新类型映射为预定义的数据契约。
- 由于Serializable特性可以直接操作成员字段,使得封装了字段访问的属性形同虚设。
- 访问字段的最好办法是通过属性添加它们的值,而Serializable却破坏了属性的封装性。
- 最后,Serializable特性并没有直接支持版本控制(Versioning),而版本控制的信息却是格式器期望获取的.
- WCF提供的数据契约DataContract基本上解决了以上的问题。通常,DataContract必须与DataMember结合使用。只有应用了DataMember特性的属性才被公开到元数据中。虽然DataMember特性也可以应用到对象的字段上,但WCF并不推荐这样做. 即使DataMember特性被直接应用到字段上,在导入的客户端定义仍然会以属性来表示。它会将字段名作为属性名,而导入的定义中,则在属性名后加上Field后缀作为字段名。但我们也可以手工修改客户端的定义.
- 如果数据契约的数据成员为私有的,导入的客户端定义会自动修改为公有的。“当DataMember特性应用到属性上时(不管是服务还是客户端),该属性必须具有get和set访问器。如果没有,在调用时就会抛出InvalidDataContractException异常。因为当属性自身就是数据成员时,WCF会在序列化和反序列化时使用该属性,使开发者能够将定制逻辑应用到属性中。”不要将DataMember特性既应用到属性上,又应用到相对应的字段上,这会导致导入的成员定义重复.
如果服务端的数据被标记为Serializable特性,在导入这样的定义时,会使用DataContract。而且“对于每一个可序列化的成员,不管是公有的还是私有的,都是数据成员。”
WCF不完全支持面向对象: 首先WCF并不支持Liskov替换原则(LSP),“默认情况下,我们不能用数据契约的子类去替换基类。”虽然WCF引入了Known Types(已知类型)来解决这一问题,这样的设计无疑会引入父类与子类之间的耦合度。因为在我们设计父类的时候,就必须事先知道子类的定义。当我们需要扩展子类时,还需要修改父类的定义。WCF引入的服务已知类型,比较已知类型而言,有一定程度的改善。因为它可以将父类与子类在层级上的耦合度缩小到方法级上。但这样的耦合,依然是不可接受的. 当然,服务已知类型也可以应用到契约接口上,此时,该契约以及实现该契约的所有服务包含的所有操作都能够接收已知的子类.
- 为了解决这一问题,WCF提供了配置已知类型的方法. 我们配置的已知类型必须是类型的fullname。包括命名空间、版本号、Culture等. 如果已知类型对于另一个程序集而言是内部(internal)类型,要添加一个已知类型,只有使用配置文件声明它.
- WCF对于枚举、委托、DataSet和DataTable、泛型、集合的支持有限.
- 枚举:自身支持序列化,所以默认就是在数据契约里,当只需要其一部分被序列化时,使用EnumMember表示出需要的数据.在客户端只有被EnumMember的数据才出现在枚举定义里.
- 委托:WCF对委托以及事件的支持都不够好。这是因为委托的内部调用列表的具体结构是本地的,客户端或服务无法跨服务边界共享委托列表的结构。此外,我们不能保证内部列表中的目标对象都是可序列化的,或者都是有效的数据契约。这会导致序列化的操作时而成功,时而失败。因此,最佳实践是不要将委托成员或事件作为数据契约的一部分.
- 数据集和数据表: 是可以序列化的.在服务契约中使用该类型,代理类中只会有一个定义,而没有任何代码.我们可以手工修改. 然而,WCF的最佳实践则是避免使用DataTable和DataSet,以及使用DataTable和DataSet的类型安全的子类。这种方式过于繁琐。而且,这些数据访问类型都是特定的.NET类型。在序列化时,它们生成的数据契约样式过于复杂,很难与其它平台进行交互。在服务契约中使用数据表或者数据集还存在一个缺陷,那就是它可能暴露内部的数据结构。同时,将来对数据库样式的修改会影响到客户端。虽然在应用程序内部可以传递数据表,但如果是跨越应用程序或公有的服务边界发送数据表,却并非一个好的主意。通常情况下,更好的做法是暴露数据的操作而非数据本身。最好的做法是将DataTable转换为数组类型.
- 泛型: 不能在数据契约里定义泛型,但是,可以在服务段使用泛型,但是在生成的数据契约定义中,泛型被具体的类型(<原有名>Of<类型参数名><哈希值>)代替.WCF还支持将自定义类型作为泛型参数。此外,还可以通过数据契约的Name属性为导出的数据契约指定不同的名字.
- 集合:WCF支持泛型集合、定制集合.但是有很多限制.对于自定义的集合应该采用
- [KnownType(typeof(Document))]
- [CollectionDataContract]
- [Serializable]
- public class DocumentList:IList<Document>
- 这样,客户端应用程序可以直接使用数据契约,仍然能够识别.
WCF之数据契约的更多相关文章
- 重温WCF之数据契约中使用枚举(转载)(十一)
转载地址:http://www.zhuli8.com/wcf/EnumMember.html 枚举类型的定义总是支持序列化的.当我们定义一个新的枚举时,不必应用DataContract特性,就可以在数 ...
- 重温WCF之数据契约和序列化(四)
一.数据契约 1.使用数据协定可以灵活控制哪些成员应该被客户端识别. [DataContract] public class Employee { [DataMember] public string ...
- WCF中数据契约之已知类型的几种公开方式
WCF中传输的数据不想传统的面向对象编程,它只传递了一些对象的属性,但是自身并不知道自己属于什么对象,所以,他没有子类和父类的概念,因而也就没有Is-a的关系,所以在WCF中,如果想维持这种继承关系, ...
- WCF 之 数据契约
前面几篇讲的都只能传递string类型的简单参数,数据契约就是用来解决如传递一个带有多个属性的Class类型的对象的. WCF推荐使用数据契约的方式实现数据的序列化.这部分的内容很好理解但是很重要,先 ...
- WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)
原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济 ...
- 跟我一起学WCF(7)——WCF数据契约与序列化详解
一.引言 在前面博文介绍到,WCF的契约包括操作契约.数据契约.消息契约和错误契约,前面一篇博文已经结束了操作契约的介绍,接下来自然就是介绍数据契约了.所以本文要分享的内容就是数据契约. 二.数据契约 ...
- WCF分布式开发步步为赢(7):WCF数据契约与序列化
本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤.那么序列化是什么?为 ...
- WCF契约之---服务契约 、数据契约、 消息契约
本篇博文只是简单说下WCF中的契约的种类.作用以及一些简单的代码示例.在WCF中契约分为服务契约.数据契约和消息契约.下面对这几种契约进行简单的介绍. 服务契约 服务契约描述了暴露给外部的类型(接口或 ...
- WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用
原文:WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经> ...
随机推荐
- Flex数据交互之Remoting[转]
Flex数据交互之Remoting 一 前言 Flex数据交互常用的有三种方式:WebService.HttpService以及Remoting. WebService方式已在这篇文章中给出,这篇文章 ...
- leetcode二分查找问题整理
自从做完leetcode上的三道关于二分查找的题后,我觉得它是比链表找环还恶心的题,首先能写出bugfree代码的人就不多,而且可以有各种变形,适合面试的时候不断挑战面试者,一个程序猿写代码解决问题的 ...
- mysql基本定义--数据类型
浮点数类型与定点数类型: MySQL中使用浮点数类型和定点数类型来表示小数. 浮点数类型包括单精度浮点数(float型)和双精度浮点数(double型).定点数类型就是decimal型. OK,现在我 ...
- 基于css3的文字3D翻转特效
一款基于css3的文字3D翻转特效.这款特效当鼠标经过文字的时候3D翻转显示阴影.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div class="compo ...
- UIScrollView做循环图片
#import "ViewController.h" #define IMAGE_COUNT 6 @interface ViewController () { UIImageVie ...
- Android 高级UI设计笔记12:ImageSwitcher图片切换器
1. ImageSwitcher ImageSwitcher是Android中控制图片展示效果的一个控件,如:幻灯片效果...,颇有感觉啊.做相册一绝 2. 重要方法 setImageURI(Uri ...
- iOS 设计模式之单例
设计模式:单例 一. 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并 ...
- Liunx下全局安装 Composer
我把它放在系统的PATH目录中,这样就能在全局访问它. curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/l ...
- IDE改为AHCI后系统无法启动的解决办法
1.intel CPU 一.找到HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Msahci,“Start”项值改为“0”. 二.重启,进入b ...
- React Native视频播放(iOS)
网站链接:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/learn-react-native-video/ React Nativ ...