3、集合与KnowType
集合类型和非集合类型在多态增加KnowType类型方面是不同的,关于非集合方面增加KnowType的详细情况请我以前的文章:WCF Data Contract之KnowType。集合类型在增加KnowType类型遵守以下规则:
3.1、集合类型是以多态方式来代替其他集合或集合接口的,您不需要将这样的集合类型添加到KnowType类型中。例如上例中Customer2类中的addresses,你可以将List
3.2、当您以多态方式使用集合来代替非集合类型时,则需要将它们添加到已知类型。 例如,如果您声明一个 Object 类型的数据成员并将其用于发送 ArrayList 的一个实例,则需要将 ArrayList 添加到已知类型中。
3.3、等价的集合只能应用KnowTypeAttribute属性来将其增加到KnowType列表中一次。例如:不能将ArrayList和Object[]都添加到相同类的KnowType列表中
4、定制集合的数据契约(协定)
我们可以使用CollectionDataContractAttribute的下列属性来指定集合的数据契约的相关名称及命名空间:
4.1、Name属性来指定集合数据契约的名称(如果没有使用此属性,将使用集合类型的名称)
4.2、Namespace属性来指定其命名空间
4.3、ItemName 属性来指定循环元素的名称
4.4、针对字典集合还可以用KeyName和ValueName来指定键和值的名称
例如,我们将第一节的例子更改成如下所示:
|
此类将被序列化成:
http://schemas.datacontract.org/2004/07/WCFTestSerializer"> |
对于定制数据契约的集合类型来说,前面所述的非定制数据契约的集合等价规则将失效。所以要尽量避免使用CollectionDataContractAttribute。
5、集合的反序列化
缺省情况下,使用Svcutil.exe生成客户端代理时,列表集合将反序列化成数组,字典集合将反序列化成Dictionary泛型。我们也可以通过/collectionType 命令行开关(简写形式是 /ct)来指定我们希望反序列化的集合类型(请记住,您还必须使用 /reference 开关(简写形式是 /r)指定引用的集合类型的程序集)。如果该类型是泛型,则必须在类型后面跟有反引号和泛型参数的数目。例如前面的例子中的Customer1类可以通过下面的命令在客户端使用List泛型:SvcUtil http://localhost:8000/ 。
/r:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll |
6、DataContractAttribute和CollectionContractAttribute
对于集合而言,WCF框架将隐含地自动的为集合类型应用CollectionDataContractAttribute属性的,这就是为什么你不需要为集合应用任何属性就可以在数据契约中使用的原因。但要注意:
(1)如果我们新建的集合类型是继承已有的集合类型如List
(2)如果我们新建的集合类型是实现了集合接口例如IList
(3)针对应用CollectionDataContractAttribute属性或者缺省不应用任何属性的集合类型,如果其内部有应用了DataMemberAttribute的属性或字段,在序列化时系统将忽略。
7、WCF中对集合类型的要求限制
不是所有的集合类型都可以在WCF中使用,只有满足以下要求才可以使用:
7.1、该集合类型有一个缺省的构造函数
7.2、该集合类型有一个名为Add的方法
这是因为在反序列化集合类型时,WCF框架首先调用该集合类型的无参数的构造函数,然后通过非静态的Add方法来将循环元素增加到集合中。所以以上限制主要是针对反序列化而设定的。
8、集合中的一些高级规则
8.1、WCF框架在序列化时支持集合的集合,也支持数组的数组(交错数组),但不支持多唯数组。
8.2、字节数组和 XmlNode 数组是特殊的数组类型,将被视为基元,而不是集合。 序列化字节数组会产生单个包含一个 Base64 编码数据块的 XML 元素,而不是为每个字节都生成一个单独的元素。(笔者认为这是为了性能的考虑才这么处理的。)
8.3、如果集合类型实现了IXMLSerializable接口,假设类型为MyType:IList
8.4、在对集合进行序列化时,将调用集合类的GetEnumerator 方法来得到集合的内容,在反序列化时将首先调用该集合类型的无参数的构造函数,然后通过非静态的Add方法来将循环元素增加到集合中。(注:虽然这与大家在MSDN的帮助文档中看到的不同,认为字典集合将调用get_Keys和get_Values,以及IList将调用索引器,但笔者使用VS2008验证时没有得到以上方法被调用的结论,所以笔者认为是MSDN文档滞后或有误,如果各位看官能得到和MSDN吻合的结论麻烦告诉一声。)
8.5、如果集合类型同时应用了Serialized属性或实现了ISerializable接口,WCF框架将忽略它们;但是如果集合类型不满足集合类型要求(例如缺少Add)方法,那么将按照Serialized或ISerializable来处理;但如果你对该集合同时应用了CollectionDataContract属性而且又不满足集合要求,那么将抛出InvalidDataContractException,而不是按照Serialized或ISerializable来处理。
8.6、不能向实现了IXmlSerializable接口的类型使用CollectionDataContractAttribute属性,否则会抛出InvalidDataContractException.向非集合应用CollectionDataContractAttribute属性以及非字典集合指定KeyName或者ValueName属性也都将抛出此异常。
| 共2页: 上一页 [1] 2 | ||
|