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,但都不适用于WCF或SQA的场景,因为他们都序列化了所有用到的类型信息(可能依赖于.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会影响所有使用此DataContract的ServiceContract,如果想在ServiceContract上控制的话,则使用ServiceKnownType Attribute,它可以在ServiceContract上,也可以在OperationContract上加,只会影响当前的ServiceContract或OperationContract
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接口,因为Service的Metadata中不包括接口,只包括实现类和结构,Client Proxy会用Object类型代替Icon接口的参数类型,并加一个[ServiceKnownType(typeof(Object))]的Attribute,用户可以去掉此Attribute并添加ICon到声明并代替Object,但不能用Con代替Object(在Service端使用ICon的情况下)
3. Data Contract Equivalence
i. 两个具有相同结构的DataContract是等价的,尽管名字不同,但可以使用DataMember Attribute的Name属性进行重命名
ii. 等价的DataContract的成员序列化顺序必须是一致的
iii. 可以使用DataMember的Order指定被序列化的顺序
4. Versioning
i. New Member
1. 当Service/Client发送具有New Member的DatcContract到另一端时,数据被正确接收,但New Member将被忽略
ii. Missing Member
1. 当Service/Client发现接受到的DataContract有Missing Member时,将会赋予其默认值,而不会有任何动作
2. 可以使用OnDeserializing事件赋予Missing Member正确的值
3. 可以使用DataMember的IsRequired=True 强制DataMember必须被赋值
4. 当在DataContract上使用[Serializable] Attribute时,每个DataMember都的IsRequired都被设为True
5. 如果想在[Serializable]中使用可选DataMember,可以使用[OptionalField] Attribute
iii. Versioning Round-Trip
1. 当遇到New-Old-New的场景时,DataContract中的New Member在Old端会丢失掉,从而使最后一步获取不到正确的信息。为了解决这个问题,可以让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. DataSet和DataTable可以在ServiceContract中使用,因为他们能被序列化,但生产Proxy时只会生成DataSet和DataTable的架构定义,客户可以把他们移除掉而使用ADO.NET代替
ii. 可以使用强类型的DataSet和DataTable,客户端会生成相应的代码
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 阅读(1712) 评论(0) 编辑 收藏 举报