WCF学习系列(4)————数据协定
在前面看了如何创建WCF程序,WCF与客户端通讯几种模式,WCF配置,WCF生成客户端代理类,以及WCF的承载。现在我们来看WCF数据协定。
数据协定:在WCF客户端和服务端之间进行数据传递的一种包装方式,一般是参数和返回值来公开数据协定,当我们有很多参数时候,就不利于我们编程了。所以在客户端和服务端之间,我们可以用一种包装方式来传递中间的数据。其实数据协定就是很平常的类,只不过类加了WCF的修饰DataContract,其中类里面的元素要公开可以用DataMember来修饰,平常使用我们协定,跟使用普通类一样。
在默认情况下,WCF使用称为数据协定序列化程序的序列化引擎对数据进行序列化和反序列化(与XML进行数据转换),所有的.net framework基元类型(整形,字符串)以及那些被默认为基元的类型(DateTime和,XMLElement)不需要做其他任何序列化操作,这些都被称为拥有默认的数据协定。复杂类型我们必须定义数据协定以便进行序列化,复杂类型可以是类,结构,枚举等。成员加了DataMember之后就成为数据成员,进行序列化。如果没有DataMember修饰的成员,就不会被序列化,公开。DataMember可以应用与字段属性事件等。访问修饰符对数据协定是没有影响的,注意不能用DataMember用在静态成员上面。在序列化期间,我们也是通过get方式来获取序列化的属性值。在反序列化期间,首先创建一个未初始化的对象,而不在该类型上调用任何的构造函数,然后反序列化所有成员,在反序列化期间,也是为属性数据成员调用get代码,将属性设置为要反序列化的值。对于即将生效的数据协定,它必须能序列化其所有成员。另外,泛型类型的处理方式与非泛型类型完全相同。
[DataContract] public class MyList<T> { [DataMember] T myData }
如代码所示,我们T能序列化,那我们泛型类也可以序列化。定义的时候不知道能不能序列化,如果实例化的时候我们的T可以序列化,那我们的MyList就可以序列化,然后我们也需要进行协定。
数据协定类的构造函数,在序列化的时候是不会去序列化构造函数的,只是在实例化的时候才调用。例子在这就不写了。创建WCF服务应用程序就可以。
数据协定的名称:如果用namespace,和那么协定不同的数据,那么他们是等效的。数据成员按照order来排序。有Order的按照数字排列,没有的按照字母排列。子类序列化,先序列基类的成员,然后序列没有用order修饰的成员,最后序列有order修饰的。
数据协定等效性 -要使用数据协定等效性,其命名空间和名称必须相同。此外,某一端上的数据成员还必须在另一端上具有等效的数据成员。 -要使数据成员等效,其名称必须相同。此外,它们还必须标示同一类型的数据,也就是说,其数据协定必须等效。 -如果同一端(发送方或接收方)存在两种类型,而其数据协定又不等效(例如,它们的数据成员不同),则不应为它们指定相同的名称和命名空间。否则,可能会引发异常。 例如下面Customer与Person是等效的
[DataContract] publicclassCustomer { [DataMember] publicstringfullName; [DataMember] publicstringtelephoneNumber; } [DataContract(Name="Customer")] public class Person { [DataMember(Name="fullName")] private string nameOfPerson; private string address; [DataMember(Name="telephoneNumber")] private string phoneNumber; }
数据成员顺序和数据协定等效性
- 使用 DataMemberAttribute 类的 Order 属性可能会影响数据协定等效性。其成员必须以相同顺序出现,数据协定才能等效。默认顺序是按字母顺序。
- 数据排序的基本规则包括:
- 如果数据协定类型是继承层次结构的一部分,则其基类型的数据成员始终排在第一位。
- 排在下一位的是当前类型的数据成员(按字母顺序排列),这些成员未设置 DataMemberAttribute 属性(attribute) 的 Order 属性(property)的任何数据成员。这些成员首先按 Order 属性的(property)
- 在下面是设置了 DataMemberAttribute 属性(attribute)的 Order 属性(property)的任何数据成员。这些成员首先按 Order 属性的值排序,如果多个成员具有特定的 Order 值,则按字母顺序排列。
数据协定已知类型
- 发送的数据协定源自预期的数据协定, 要传输的信息的声明类型是接口,而非类、结构或枚举, 要传输的信息的声明类型是 Object
- 有些类型(包括.NET Framework类型)具有属于上述三种类别之一的成员。例如,Hashtable 使用 Object 在哈希表中存储实际对象 KnownTypeAttribute
- 通过首先检查传入消息选择为反序列化而实例化的类型,以确定消息内容遵循的数据协定。然后反序列化引擎尝试查找实现与消息内容兼容的数据协定的CLR类型。反序列化引擎在此过程中允许的候选类型集称为反序列化程序的“已知类型”集。 让反序列化引擎了解某个类型的一种方法是使用 KnownTyoeAttribute。 不能将属性应用于单个数据成员,只能将它应用于整个数据协定类型。 将属性应用于可能为类或结构的“外部类型”。在其最基本的用法中,应用属性会将类型指定为“已知类型”。只要反序列化外部类型的对象或通过其成员引用的任何对象,这就会导致已知类型成为已知类型集的一部分。可以将多个 KnowTypeAttribute 属性应用于同一类型。
.数据协定版本管理
- 重大更改与非重大更改, 对数据协定的更改可能是重大更改,也肯能是非重大更改。对数据协定进行非重大更改时,使用较早版本的应用程序和使用较新版本协定的应用程序可以互相通信。另一方面,如果进行重大更改,则会阻止单向或双向通信。
下面的更改始终是重大更改
1: 更改数据协定的 Name 或 Namespace 值。
2:通过 DataMemberAttribute 的 Order 属性来更改数据成员的顺序。
3: 重命名数据成员
4: 更改数据成员的数据协定
5:添加或移除数据成员
6:将具有类外字段的类型反序列化为具有缺失字段的类型时,将忽略额外的信息。
7: 具有缺失字段的类型反序列化为具有额外字段的类型时,额外字段将保留其默认值,通常为零活 null。
8: 不需的数据成员
9:通过将 DatamemberAttribute 的 IsRequired 属性设置为 true,可以将数据成员标记为必需的数据成员。如果反序列化时缺少必需的数据,则会引发异常,而不是将数据成员设置为其默认值。
10:添加必需的数据成员是重大更改。
11: 移除在任何早期版本中标记为必需成员的数据成员也是重大更改。
12: 将 IsRequired 属性值从 true 更改为 false 不是重大更改;如果类型的任何早期版本都没有相应数据成员,将该属性值从 false 更改为 true 就可能是重大更改。
上面内容有些自己做的笔记,有些从其他地方拷贝过来做个标记。