您的位置:首页 > 其它

Programming WCF Services 学习笔记三、Data Contract

2008-06-03 10:29 549 查看
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

(未完待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: