您所在的位置: 首页>>开发>>语言&工具>>

WCF Data Contract之集合类型(2)

http://developer.51cto.com  2008-03-14 16:30  LazyBee  博客园  我要评论(0)
  • 摘要:在.Net中将实现了IEnumerable接口的所有类型(包括数组和泛型)都称之为集合类型。把其中实现了IDictionary接口或泛型IDictionary接口的集合类型称为字典集合,剩下的其他集合类型为列表集合。
  • 标签:WCF  Data Contract  集合  类型

3、集合与KnowType

集合类型和非集合类型在多态增加KnowType类型方面是不同的,关于非集合方面增加KnowType的详细情况请我以前的文章:WCF Data Contract之KnowType。集合类型在增加KnowType类型遵守以下规则:

3.1、集合类型是以多态方式来代替其他集合或集合接口的,您不需要将这样的集合类型添加到KnowType类型中。例如上例中Customer2类中的addresses,你可以将List的实例赋值给它,而不需要将List增加到KnowType类型列表中。

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来指定键和值的名称

例如,我们将第一节的例子更改成如下所示:

[CollectionDataContract(Name = " telephones", ItemName = "telephone",

KeyName = "Index", ValueName = "Number")]

public class MyDictionary : Dictionary

{

public new Dictionary.Enumerator GetEnumerator()

{

Dictionary innerObject = new Dictionary {

{ 1, "010-82371234" },

{ 2, "021-56781234" } };

return innerObject.GetEnumerator();

}

}

此类将被序列化成:

http://schemas.datacontract.org/2004/07/WCFTestSerializer">

1

010-82371234

2

021-56781234

对于定制数据契约的集合类型来说,前面所述的非定制数据契约的集合等价规则将失效。所以要尽量避免使用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
/ct:System.Collections.Generic.List`1

6、DataContractAttribute和CollectionContractAttribute      

对于集合而言,WCF框架将隐含地自动的为集合类型应用CollectionDataContractAttribute属性的,这就是为什么你不需要为集合应用任何属性就可以在数据契约中使用的原因。但要注意:

(1)如果我们新建的集合类型是继承已有的集合类型如List,那么我们就不能对新建的集合类型应用DataContractAttribute,否则运行时会抛出InvalidDataContractException,但你可以应用CollectionDataContractAttribute来定制集合类型的数据契约。例如[DataContract]public class MyList:List{…}的集合定义将抛出异常。

(2)如果我们新建的集合类型是实现了集合接口例如IList,IDictionary的话,我们可以对此类型应用DataContractAttribute属性,这样的话此类型将作为普通的数据契约类型,而不是将其作为集合类型来处理。也就是WCF框架将只序列化其中应用了DataMemberAttribute属性的成员。当然你也可以不应用任何属性来让系统缺省作为集合类型来处理。(你也可以使用CollectionDataContractAttribute来定制数据契约)

(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,IXMLSerializable{…},WCF框架将根据在数据契约中声明的类型来进行序列化,如果声明的是集(接口)如IList,那么该类型将被认为是列表集合来序列化,如果声明的是IXMLSerializable,那么将按照IXMLSerializable来进行序列化,当然需要将该类型加到KnowType类型列表中。如果声明的是该类型本身(如MyType),那么将按照IXMLSerializable的规则来进行序列化。

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
【内容导航】
WCF开发基础
深入Vista应用程序开发
走向银光 —— 一步一步学Silverlight2
让你的代码“炫”起来——WPF开发教程
WebSphere 实现SOA的利器
 
 验证码: (点击刷新验证码)   匿名发表
  • Visual C++ 完全自学宝典

  • 作者:强锋科技,朱洪波
  • Visual C++ 6.0是微软公司为程序人员提供的Visual Studio 6.0工具套件中的重要组成部分。本书由浅入深地介绍使用Visual C++ 6.0..
Copyright©2005-2008 51CTO.COM 版权所有