Programming WCF Services 学习笔记三、Data Contract

 

1.         Serialization

                         i.              DataContract保护在Service Metadata中,客户端需要把DataContract转换为可使用的本地类型

                       ii.              .Net使用序列化来传递DataContract

                      iii.              一次客户端调用的序列化过程:

                      iv.             

                       v.              DataContract不会被序列化,除非打[Serializable] Attribute

                      vi.              对于有些临时性的属性(例如数据库连接),要打[NonSerialized] Attribute,禁止序列化,在反序列化时再恢复

                    vii.              .Net提供了两种序列化的格式:二进制和SOAP,但都不适用于WCFSQA的场景,因为他们都序列化了所有用到的类型信息(可能依赖于.NET Framework),这对于客户端是不可接受的,因为WCF允许不同类型的客户端

                   viii.              WCF提供了专门的序列化技术DataContractSerializer,它只序列化DataContract数据而忽略类型信息

                      ix.              DataContract可以嵌套使用

                       x.              可以对DataContract进行事件跟踪,例如通过使用[OnDeserialized]在反序列化后恢复数据库连接

2.         Data Contract Hierarchy

                         i.              DataContract可以继承,但[DataContract] Attribute不允许继承,所以在继承树中的任何一个级别,都要显式使用[DataContract] Attribute

                       ii.              DataContract不能用子类代替父类使用,因为WCF在反序列化时不知道子类的结构,要想使用子类代替父类,要在父类定义时加[KnownType(typeof(子类))] Attribute

                      iii.              如果Client端要想使用子类代替父类的话,也要使用KnownType Attribute

                      iv.              应用在DataContract上的KnownType会影响所有使用此DataContractServiceContract,如果想在ServiceContract上控制的话,则使用ServiceKnownType Attribute,它可以在ServiceContract上,也可以在OperationContract上加,只会影响当前的ServiceContractOperationContract

                       v.              ServiceKnownType Attribute不会被客户端感知,而会被感知为KnownType并且应用到对应当DataContract上,但用户可以修改客户端代理

                      vi.              可以在一个ServiceContract上使用多个ServiceKnownType Attribute,但有一点要记住,不要不添加父类就添加子类

                    vii.              可以把KnownType放到配置文件中:

system.runtime.serialization"dataContractSerializer"declaredTypes

                   viii.              如果名为Con DataContract实现了ICon接口的话,可以在OperationContract上接受ICon类型的参数,然后加[ServiceKnownType(typeof(Con))],但不要再ServiceKnownType上使用Icon接口,因为ServiceMetadata中不包括接口,只包括实现类和结构,Client Proxy会用Object类型代替Icon接口的参数类型,并加一个[ServiceKnownType(typeof(Object))]Attribute,用户可以去掉此Attribute并添加ICon到声明并代替Object,但不能用Con代替Object(在Service端使用ICon的情况下)

3.         Data Contract Equivalence

                         i.              两个具有相同结构的DataContract是等价的,尽管名字不同,但可以使用DataMember AttributeName属性进行重命名

                       ii.              等价的DataContract的成员序列化顺序必须是一致的

                      iii.              可以使用DataMemberOrder指定被序列化的顺序

4.         Versioning

                         i.              New Member

1.         Service/Client发送具有New MemberDatcContract到另一端时,数据被正确接收,但New Member将被忽略

                       ii.              Missing Member

1.         Service/Client发现接受到的DataContractMissing Member时,将会赋予其默认值,而不会有任何动作

2.         可以使用OnDeserializing事件赋予Missing Member正确的值

3.         可以使用DataMemberIsRequired=True 强制DataMember必须被赋值

4.         当在DataContract上使用[Serializable] Attribute时,每个DataMember都的IsRequired都被设为True

5.         如果想在[Serializable]中使用可选DataMember,可以使用[OptionalField] Attribute

                      iii.              Versioning Round-Trip

1.         当遇到New-Old-New的场景时,DataContract中的New MemberOld端会丢失掉,从而使最后一步获取不到正确的信息。为了解决这个问题,可以让DataContract实现IExtensibleDataObject接口,New Member在序列化时会存入此接口的ExtensionData中而不会丢失

2.         可以在ServiceContract上使用[ServiceBehavior(IgnoreExtensionDataObject = ture)]使此ServiceContract忽略所有的Unknown Data Member

5.         Enumerations

                         i.              枚举可以自动被序列化,而不用使用DataContract Attribute

                       ii.              要想排除枚举中的某个值,可以使用[EnumMember] Attribute显式标记,不标记的即被排除

                      iii.              [EnumMember]还可以使用Value属性给值命名

6.         Delegates and Data Contracts

                         i.              Delegates可以自动被序列化

                       ii.              事件可以被序列化,但需要使用[field:DataMember] Attribute

                      iii.              实际上,Delegate引用的是本地的方法,传递本地方法的引用到Service的另一端是没有意义的,所以传递Delegate也是没有意义的,尽管WCF不会报错

                      iv.              要排除对Delegate的序列化,可以不使用DataMember,或在Serializable时使用[NonSerialized]

7.         Data Sets and Tables

                         i.              DataSetDataTable可以在ServiceContract中使用,因为他们能被序列化,但生产Proxy时只会生成DataSetDataTable的架构定义,客户可以把他们移除掉而使用ADO.NET代替

                       ii.              可以使用强类型的DataSetDataTable,客户端会生成相应的代码

8.         Generics

                         i.              DataContract上可以使用泛型,但ServiceContract上不允许接收泛型参数,因为客户端不止是.NET平台,ServiceContract上要使用具体的类型参数

                       ii.              客户端生成Proxy时会为DataContract生成<类名>Of<泛型类型><哈希值>

                      iii.              当使用自定义的泛型类型时,才会有<哈希值>,但可以对泛型DataContract使用Name属性命名来避免出现<哈希值>

9.         Collections

                         i.              ServiceContract中可以使用Collection,但元数据中不会包含Collection,会转换成Array

                       ii.              只要Collection中有Add()方法,就可以把Collection转换成Array

                      iii.              可以使用CollectionDataContract Attribute使客户端生成泛型而取代Array,从而使接口一致

                      iv.              可以在Client端引用CllectionType来使用Client端的类型(使用SvcUtil /ct

                       v.              Client可以修改Proxy的代码,用Collection代替Array

                      vi.              ServiceContract中可以是用迭代,但(.net3.0)不能使用yield return 立即返回(3.0可以)

                    vii.              DataContract中可以使用Dictionary

(未完待续)

posted on 2008-06-03 10:29  zhaojunqi  阅读(1702)  评论(0编辑  收藏  举报

导航