《WCF技术内幕》翻译23:第2部分_第5章_消息:XmlDictionaryReader和回到Message

XmlDictionaryReader类型

(本节主要讲解的是XmlDictionaryReader类型,如何实例化一个对象,如何使用其来反序列化XmlDictionaryWriter处理的数据。最后是:回到Message)
XmlDictionaryReader抽象类型继承自 System.Xml.XmlReader,因此继承了很多XmlReader的特性。和 XmlReader一样,XmlDictionaryReader定义了几个工厂方法,他们返回的是XmlDictionaryReader的子类型的实例。更确切地说,XmlDictionaryReader包装了一个Stream,并定义了许多以Read开头的方法。因此,由于继承的层次关系,使用XmlDictionaryReader和XmlReader很相似。
和XmlReader不同,XmlDictionaryReader的目的是为了读取序列化的和编码过的 XML Infosets ,并且可以由选择地借助XmlDictionary来实现语义压缩的反向处理。作用上, XmlDictionaryReader和XmlDictionaryWriter正好相反,并且2个类型的对象模型非常相似。让我们从XmlDictionaryReader的创建方法开始学习,然后详细研究如何使用它的Read方法。因为XmlDictionaryReader和XmlDictionaryWriter的相似性,本节会比上一节XmlDictionaryWriter要简短一些。
创建一个XmlDictionaryReader对象
XmlDictionaryReader类型定义了几个工厂方法,所有这些方法都直接或者间接地,接受一个 Stream 或Byte[]的引用。通常来说,面向stream的方法与面向buffer的方法很相似。绝大部分,这些工厂方法都是重载一下4个方法: CreateDictionaryReader, CreateTextReader, CreateMtomReader和CreateBinaryReader,它们的行为与 XmlDictionaryWriter的相同名字工厂方法对应。为了避免重复,我们将会关注XmlDictionaryReader的工厂方法的显著特性上。
几个工厂方法接受一个Stream的引用,这些面向stream的工厂方法使用的其它参数包含一个 XmlDictionaryQuotas对象的引用和一个OnXmlDictionaryReaderClose委托。在所有的情况下,前者调用后者,为XmlDictionaryQuotas和OnXmlDictionaryReaderClose参数传递null引用。
XmlDictionaryQuotas类型是一个状态容器,它用来定义与 XML反序列化相关的重要的阀值。例如,这个类型定义反序列化中用到的节点深度的最大值、反序列化最大的String长度、消息体的最大数组长度等等【老徐备注1】
OnXmlDictionaryReaderClose委托在 XmlDictionaryReader 的Close方法几乎结束的时候调用。当这个委托被激活以后, XmlDictionaryReader的大部分状态被设置为null。因此,这个委托可以用来作为提醒机制(很像一个事件event),但不会提供 XmlDictionaryReader状态相关的任何有价值的信息(除非Null是有价值的)。Message编码器使用OnXmlDictionaryReaderClose委托去把 XmlDictionaryReader对象放到对象池。这些编码器依赖OnXmlDictionaryReaderClose委托这样的提醒,它会返回一个资源池里的XmlDictionaryReader实例。
一下代码演示了如何实例化一个XmlDictionaryReader对象 :
private static void CreateTextReader() {
Console.WriteLine("==== Creating XML Dictionary Text Reader ====");
MemoryStream stream = new MemoryStream();
    
// create an XmlDictionaryWriter and serialize/encode some XML
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream,
        Encoding.BigEndianUnicode, false);
writer.WriteStartDocument();
        writer.WriteElementString("SongName",
                                                            "urn:ContosoRockabilia",
                                                            "Aqualung");
writer.Flush();
stream.Position = 0;
    
// create an XmlDictionaryReader to decode/deserialize the XML
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(
        stream, Encoding.BigEndianUnicode, new XmlDictionaryReaderQuotas(),
        delegate { Console.WriteLine("closing reader"); } );
reader.MoveToContent();
Console.WriteLine("Read XML Content:{0}",reader.ReadOuterXml());
    
Console.WriteLine("about to call reader.Close()");
reader.Close();
Console.WriteLine("reader closed");
}

当以上代码执行的时候,就会产生以下输出:
 
 
==== Creating XML Dictionary Text Reader ====
Read XML Content:
<SongName xmlns="urn:ContosoRockabilia">Aqualung</SongName>
about to call reader.Close()
closing reader
reader closed
着重指出一下,XmlDictionaryReader的其它工厂方法接受的参数和XmlDictionaryWriter的工厂方法几乎一一对应。这些参数与在 XmlDictionaryWriter类型里的作用一样。
借助XmlDictionary生成XML数据
既然已经看了如何实例化XmlDictionaryWriter和 XmlDictionaryReader,现在我们就学习一下如何使用XmlDictionary读取二进制编码的XML。如下面的代码所示,这与你在XmlDictionaryWriter里看到的一样:
MemoryStream stream = new MemoryStream();
// create the dictionary and add dictionary strings
XmlDictionary dictionary = new XmlDictionary();
List<XmlDictionaryString> stringList = new List<XmlDictionaryString>();
stringList.Add(dictionary.Add("SongName"));
stringList.Add(dictionary.Add("urn:ContosoRockabilia"));
    
// use an XmlDictionaryWriter to serialize some XML使用XmlDictionaryWriter序列化一些XMl
using (XmlDictionaryWriter writer =
        XmlDictionaryWriter.CreateBinaryWriter(stream, dictionary, null)) {
    
// write using the dictionary - element name, namespace, value
writer.WriteElementString(stringList[0], stringList[1], "Aqualung");
writer.Flush();
Console.WriteLine("Using Dictionary, wrote {0} bytes",
                                        stream.Position);
stream.Position = 0;
Byte[] bytes = stream.ToArray();
Console.WriteLine(BitConverter.ToString(bytes));
    
// create an XmlDictionaryReader passing the Stream创建XmlDictionaryReader并传递Stream
// and an XmlDictionary
XmlDictionaryReader reader =
        XmlDictionaryReader.CreateBinaryReader(stream, dictionary, new
            XmlDictionaryReaderQuotas());
reader.Read();
Console.WriteLine("data read from stream:\n{0}\n",
        reader.ReadOuterXml());
当代码执行的时,输出一下结果:
XmlDictionaryWriter (Binary w/dictionary) wrote 14 bytes
42-00-0A-02-99-08-41-71-75-61-6C-75-6E-67
data read from stream:
<SongName xmlns="urn:ContosoRockabilia">Aqualung</SongName>
注意到传递到CreateBinaryWriter方法上的 XmlDictionary和传递到XmlDictionaryReader方法上的XmlDictionary是一个对象的引用。诚然,传递同一个对象的引用的是有些粗糙但是能保证XmlDictionaryWriter 和XmlDictionaryReader使用一个词汇表,但是它说明了 XmlDictionaryReader可以解释XmlDictionaryWriter使用XmlDictionary压缩的数据。

回到Message类型

既然我们已经研究过了序列化和编码一个Message的相关类型,现在该重新关注一下 Message类型了。Message对象模型初略估计包含45个 public或protected的成员。这些成员中包含返回 Message实例的工厂方法、序列化Message的方法、反序列化Message的方法、返回Message信息的属性、处理Message头部的属性和清理Message的方法。
【老徐备注】
1.    为交换的 Soap 消息指定复杂性约束的 XmlDictionaryReaderQuotas 。下面的备注部分中提供了这些约束的默认值。
这些复杂性约束可以抵御某种类型的拒绝服务 (DOS) ***,这些***试图利用消息复杂性来占用终结点处理资源。表达这些约束及其默认值的属性如下所示:
字典读取器最重要的安全功能是配额。必须为字典读取器工厂方法指定配额实例。默认构造函数创建 安全 默认值(与编码默认值相同),并且类具有静态 Max 属性,用于创建不带配额的读取器。
5.maxDepth="32"
最大节点深度
6.maxStringContentLength="8192"
最大内容长度
7.maxArrayLength="16384"
最大数组长度
8.maxBytesPerRead="4096"
最大每次读取长度
9.maxNameTableCharCount="16384"
最大 NameTableChar 的数量
我曾经在 MSDN WCF 中文论坛解释过, WCF 使用到的所有的 Max 的作用。
http://social.microsoft.com/Forums/zh-CN/wcfzhchs/thread/73f31b97-bef5-47c6-b50e-d0d3140d8efb
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值