• 从抽象层面看,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之数据契约的更多相关文章

  1. 重温WCF之数据契约中使用枚举(转载)(十一)

    转载地址:http://www.zhuli8.com/wcf/EnumMember.html 枚举类型的定义总是支持序列化的.当我们定义一个新的枚举时,不必应用DataContract特性,就可以在数 ...

  2. 重温WCF之数据契约和序列化(四)

    一.数据契约 1.使用数据协定可以灵活控制哪些成员应该被客户端识别. [DataContract] public class Employee { [DataMember] public string ...

  3. WCF中数据契约之已知类型的几种公开方式

    WCF中传输的数据不想传统的面向对象编程,它只传递了一些对象的属性,但是自身并不知道自己属于什么对象,所以,他没有子类和父类的概念,因而也就没有Is-a的关系,所以在WCF中,如果想维持这种继承关系, ...

  4. WCF 之 数据契约

    前面几篇讲的都只能传递string类型的简单参数,数据契约就是用来解决如传递一个带有多个属性的Class类型的对象的. WCF推荐使用数据契约的方式实现数据的序列化.这部分的内容很好理解但是很重要,先 ...

  5. WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)

    原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济 ...

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

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

  7. WCF分布式开发步步为赢(7):WCF数据契约与序列化

    本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤.那么序列化是什么?为 ...

  8. WCF契约之---服务契约 、数据契约、 消息契约

    本篇博文只是简单说下WCF中的契约的种类.作用以及一些简单的代码示例.在WCF中契约分为服务契约.数据契约和消息契约.下面对这几种契约进行简单的介绍. 服务契约 服务契约描述了暴露给外部的类型(接口或 ...

  9. WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用

    原文:WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经> ...

随机推荐

  1. 关于sources.list和apt-get [转载]

    个人觉得,Debian最大的方便在于用apt-get安装软件,apt-get的工作原理大概是这种:/etc/apt/sources.list文件中保存着一些server的设置,在这些server上有大 ...

  2. TP复习11

    ## ThinkPHP 3.1.2 模板中的基本语法#讲师:赵桐正微博:http://weibo.com/zhaotongzheng 本节课大纲:一.导入CSS和JS文件 1.css link js ...

  3. [Angular2 Router] Load Data Based on Angular 2 Route Params

    You can load resource based on the url using the a combination of ActivatedRouteand Angular 2’s Http ...

  4. [Express] Level 3: Massaging User Data

    Flexible Routes Our current route only works when the city name argument matches exactly the propert ...

  5. qt creator中使用qwt插件

    前提:我用mingw编译的qwt. 将qwt插件集成到qt designer非常easy.仅仅要把qwt编译的qwt_designer_plugin.dll复制到C:\Qt\Qt5.3.1\5.3\m ...

  6. MySQL ALTER语法的运用方法 && 操作索引和字段

    语法:alter_specification: ADD [COLUMN] create_definition [FIRST | AFTER column_name ] or ADD INDEX [in ...

  7. python 接口测试 、提交数据

    在测试过程中经常会遇见需要向服务器提交数据.或者进行接口测试,这个有很多方法,但是我经常用的就是使用python 编写脚本提交,方便.说说方法: 思路: 1.首先有一个提交数据的url 2.按照字典的 ...

  8. C#.net 获取当前应用程序所在路径及环境变量

    一.获取当前文件的路径 string str1=Process.GetCurrentProcess().MainModule.FileName;//可获得当前执行的exe的文件名. string st ...

  9. hdu 1228 A+B 字符串处理 超级大水题

    中文意思不解释. 很水,我本来想用switch处理字符串,然后编译不通过...原来switch只能处理整数型的啊,我都忘了. 然后就有了很挫的一大串if代码了... 代码: #include < ...

  10. VMware系统运维(九)VMware vSphere Client 安装

    1.点击下一步 2.接受协议,下一步 3.选择安装位置,下一步 4.开始安装 5.安装完成,进行登录测试. VMware vsphere 5.1 登录名为administrator    VMware ...