《WCF技术内幕》翻译21:第2部分_第5章_消息:WCF XML Stack 和 XmlDictionary

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 XmlDictionaryWriterXmlDictionaryReader。为了讨论尽可能地简单,我讲使用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 stringListstringList.Add(dictionary.Add("ReleaseDate"));stringList.Add(dictionary.Add("GoodSongs"));stringList.Add(dictionary.Add("Studio"));

因为XmlDictionary.Add方法返回一个XmlDictionaryString的实例,局部变量dictionary包含3个XmlDictionaryString对象表示“ReleaseDate”、“GoodSongs”和“Studio”。此外,局部变量stringList包含相同的3个XmlDictionaryString对象,存储在局部变量dictionary里。因为dictionary的三个对象不是公开访问的,所以必须另外存储一份,这样做实属无奈。我们可以通过迭代访问局部变量stringList看到每个XmlDictionaryString的Key 和Value属性。

Console.WriteLine("entries in Collection:");
foreach (XmlDictionaryString entry in stringList) {
 Console.WriteLine(
"Key = {0}, Value = {1}", entry.Key, entry.Value);
}
当前面的代码执行时,我们看到Key属性的值自动被赋于每个XmlDictionaryString:
整个集合如下:

Key = 0, Value = ReleaseDate
Key 
= 1, Value = GoodSongs
Key 
= 2, Value = Studio
注意到XmlDictionaryString的Key属性是由XmlDictionary.Add方法赋值的。
XmlDictionary本身并没什么用处;在WCF的XML的堆栈里它必须和其它的类型一起使用处理压缩工作。因此,现在我们看一下XmlDictionaryWriter类型,然后看看如何协调XmlDictionaryWriter和XmlDictionary一起进行压缩一个序列化和编码过的XML Infoset。
【老徐备注】
1. XmlDictionary:
实现用于优化 Windows Communication Foundation (WCF) 的 XML 读取器/编写器实现的字典。
字典在常见文本字符串和整数之间建立映射,并为压缩和解压缩 XML 提供一种有效的机制。Windows Communication Foundation (WCF) 使用静态和动态 2 种字典。
使用静态字典时,通信的两端都使用预定义的字典。
使用动态字典时,发送端可以添加其映射不在静态字典中的新字符串。动态字典与消息一起在带外发送。动态字典使用 XmlBinaryWriterSession 和 XmlBinaryReaderSession 类传输消息和映射。

 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/318599,如需转载请自行联系原作者

上一篇:【UNREAL ENGINE 游戏开发】开篇之为什么现在就要抱紧UE的大腿!(另附学习资料/交流群)


下一篇:福特公司计划投资2亿美元新建一个数据中心