• 从抽象层面看,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. SaundProgressBar

    https://github.com/eltld/SaundProgressBar

  2. 安卓开发之使用viewpager+fragment实现滚动tab页

    闲着.用viewpager+fragment实现了个滚动tab..轻拍,以后会陆续发先小东西出来..爱分享,才快乐.demo见附件.. package com.example.demo; import ...

  3. iOS xcode8提交 iOS10 “此构建版本无效” (已解决)

    近期上传应用,遇到了"此构建版本无效"的问题,如图 网查了一下,解决了这个问题:(注意:先不要急着怀疑是网络问题,重新提交,先检查问题,别问我怎么知道的...) 1:iOS10 之 ...

  4. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 5.全局防护Bypass之宽字节注入

    0x01 背景 首先我们了解下宽字节注入,宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而导致的注入漏洞.具体原 ...

  5. 关于禁止Android scrollView 因内容变化而自动滚动 android:descendantFocusability

    出现这种情况是因为你让scrollview获得了焦点,所以它才会滚动.如果你百度了以后,你可能会发现有些博客会说让焦点停在固定的一个view中就可以了.这对于不存在刷新的页面确实是可以的,但是当你出现 ...

  6. 一步一步实现iOS微信自动抢红包

    微信红包 前言:最近笔者在研究iOS逆向工程,顺便拿微信来练手,在非越狱手机上实现了微信自动抢红包的功能.   此教程所需要的工具/文件 yololib class-dump dumpdecrypte ...

  7. C# 之 读写文件

    1.使用 FileStream 读写文件 添加命名空间引用: using System; using System.Collections.Generic; using System.Text; us ...

  8. 使用异步httpclient框架做get,post提交数据

    1.将异步httpclient框架导入 下载地址:http://download.csdn.net/detail/sinat_32804317/9555641 2.代码实现 public class ...

  9. ios 加载本地html css文件 ps:css和html必须在同一文件夹下面

    NSString *path = [[NSBundle mainBundle] bundlePath]; NSURL *baseURL = [NSURL fileURLWithPath:path]; ...

  10. 最近在用placeholder ,是已有的,网上也有不少都是jq写的

    其实除了支持placeholder 的浏览器,其他用js 或jq实现的都不叫placeholder 效果,只能算上是获取焦点,或失去焦点时的一个placeholder 没有出生时就已经存在效果 很多人 ...