WCF XML Stack
Microsoft .NET Framework为了多种用途的XML处理定义了一个丰富的类型集 合。作为一个消息平台,WCF比其他.NET应用需要的正常功能还要多。例如,你 在第2章:“面向服务”里看到的一样,WCF能够产生、发送、接受、处理二进制 或者MTOM编码的XML消息。因为.NET Framework没有提供这些功能,WCF API自己 定义类型来实现这些功能,我们可以使用这些类型与Message类型直接交互。换 句话说,WCF API 定义的类型可以转换Message类型到一个特定编码格式。在 System.Runtime.Serialization.dll程序集的WCF System.Xml命名空间下,有三 个关键的类型定义它们负责序列化和编码Message类型:XmlDictionary、 XmlDictionaryWriter和XmlDictionaryReader。为了讨论尽可能地简单,我讲使 用XML消息片段来阐述这些类型,而不是使用完全格式的SOAP消息。在本章的后 面部分,你会看到这些类型是如何来序列化和编码Message类型的。
XmlDictionary类型【老徐备注1】
如它的名字的含义一样,一个XmlDictionary对象是许多对key-value的映射 。很像字典或者词汇表,XmlDictionary可以用来替代简单的表达式而不会丢失 任何含义。我们在日常生活里经常使用这种机制,但是我们却意识不到它的存在 。考虑下面我说给朋友Rusty的话:“我昨晚看了一部关于潜水艇的电影。” Rusty将会听到这个消息并且做如下解释“我昨晚看了一部关于能在水面和水下 航行的容器的电影。”第一句话比第二句话简单明了的多,它需要较少的表达时 间。这个压缩和相关处理时间可以节省,因为我和Rusty共享一个词汇表。只要 Rusty和我明白相同的词语,我们两个就可以高效地沟通。如果我对 Rusty说: “这章经过苦思冥想(elucubration)终于完成了,”他估计不知道我在说什么 。在这个例子里,我为了节约时间用了一个Rusty 不知道的单词。因此,一个所 有的参与者都知道的字典(或者是个词汇表)会提高效率。
冒着把这个比喻搞死的风险,另外有一点它也可以证明。当我对Rusty说,“ 我昨晚看了一部潜水艇的电影,”整个句子本身可以使用几种不同的方式和语言 表达。如果你知道电影(movie)和潜水艇(submarine)的意思,你或许脑子里 可以想想到这样的场景,黝黑的剧场里(或许可以闻到5块钱一通的爆米花香) 另外还有荧幕上潜水艇的身影。话句话说,句子里的这些话激起了现实世界里的 一些画面。就XML Infoset和编码而论,你可以映射XML Infoset到真实世界里的 “事物”,你也可以把这些话转换为特定的编码。
在消息应用里,XmlDictionary也许被用来压缩序列化和编码过的消息大小, 因此可以减小需要发送的消息占用的带宽。正如人们在高效地交流以前必须有一 个公共的词汇表一样,发送者和接受者在消息交换的时候必须使用兼容的 XmlDictionary对象。从内部来看,XmlDictionary定义了一个私有的可以表示 SOAP消息里元素名字、属性和XML namespace声明的key-value对列表。
在直接使用XmlDictionary以前,我们有必要详细研究一下XmlDictionary实 例里存储的数据。XmlDictionary内部存储的key-value对是 XmlDictionaryString类型的。一个XmlDictionaryString 类型定义的是一个 Int32的Key属性和一个String类型的值。尽管XmlDictionaryString定义了共有 的构造函数。 XmlDictionaryString也不是由用户代码直接创建,而是通过增加 XmlDictionaryString对象到 XmlDictionary实例里。(我们会在本节的后面部 分看到XmlDictionaryString的例子。)
XmlDictionary定义了一个无参的构造函数,还有一个很少使用的构造函数, 这个构造函数可以接受表示最大XmlDictionaryString 元素个数的Int32数字。 在构造实例结束以后,XmlDictionaryString可以通过调用实例的Add方法加入到 XmlDictionary 里。Add方法接受一个String类型,返回一个 XmlDictionaryString实例,如下所示:
XmlDictionary dictionary = new XmlDictionary();
List<XmlDictionaryString> stringList = new List<XmlDictionaryString>();
// add element names to the dictionary and store in stringList
stringList.Add(dictionary.Add("ReleaseDate"));
stringList.Add(dictionary.Add("GoodSongs"));
stringList.Add(dictionary.Add("Studio"));