《WCF技术内幕》翻译28:第2部分_第5章_消息:使用消息头(中)

《WCF技术内幕》翻译28:第2部分_第5章_消息:使用消息头(中)

大家好,又见面了,我是全栈君。

MessageHeaders类型

因为SOAP消息可能包含很多消息头块,所以在一个Message类型里,我们需要一种表示一组消息头块对象的方法。MessageHeaders就是这个作用,并且它定义了一个 MessageHeaders类型的只读属性Headers。Headers属性是我们在Message里增加、修改、查询和移除MessageHeader的主要方式。在某种意义上,本节主要是讲解MessageHeaders类型,以及可以应用到Message类型的Headers属性上的所有信息。与Message相反,在实例化一个Message之后,我们可以随便修改Headers属性的内容。MessageHeaders是一个
具体类,而不是抽象类,它不包含工厂方法。这一点值得注意,因为本章讨论过的类型都是抽象的并且定义了工厂方法。
像前面提到的一样, 
MessageHeaders,在一定层次上,是一组 MessageHeader对象。MessageHeader类型的对象模型,奇怪的是少了一个可以返回MessageHeader对象集合的成员。作为替代,MessageHeaders实现了IEnumerable<MessageHeaderInfo> and  IEnumerable接口。这意味着我们可以简单地迭代 MessageHeaders类型来查看所有的消息头块(在MessageHeaders对象赋值以后)。
 
注意 
为了完整,我必须提下MessageHeaderInfo类型,它是 MessageHeader的基类。MessageHeaderInfo定义了几个表示SOAP消息头块的属性,比如:Actor、MustUnderstand等等。太白地说,我们看不出这个类型存在的理由,因为 MessageHeader是抽象的。

创建一个MessageHeaders对象

MessageHeaders类型定义了三个公开的构造函数。这里要着重指出的是绝大多数开发人员都不会直接使用这些构造函数,因为 Message类型(子类型)底层机制会为你调用其中的一个构造函数。如果你要选择继承Message类型的话,或许需要调用其中一个构造函数去设置Message的消息头部分。
其中一个构造函数接受MessageHeaders类型的参数。构造函数会对 MessageHeaders执行深拷贝,并把它存储在MessageHeaders实例里。
另外一个构造函数接受一个MessageVersion类型的参数,如你所料,这是设置 MessageHeaders 实例的SOAP version和WS-Addressing version。最后一个构造函数接受一个MessageVersion类型和一个 Int32类型的参数。这个构造函数设置SOAP和WS-Addressing的版本,同样包括内部消息头块list里元素的个数。记住实际元素的个数可以超过Int32设置的个数。如果我们知道将要增加到 MessageHeaders对象里的消息头的个数,使用这个重载方法,它会提升性能,因为在对象的整个生命周期里早期的时候,已经设置好了合适的存储空间。

添加一个MessageHeader

一旦MessageHeaders对象实例化完毕,我们需要给它增加一个或者多个 MessageHeader对象。MessageHeaders类型定义了接受一个MessageHeader 对象作为参数的Add方法。然后把插入 MessageHeader 对象插入到消息头块列表的最末端。
如果我们需要把MessageHeader对象插入到特定的位置,我们可以使用 Insert方法。它接受一个Int32 和MessageHeader类型的参数。 Int32类型的参数表示要插入的位置,MessageHeader参数是要插入的对象。非常有意思的是MessageHeaders把MessageHeader对象存放在一个数组结构中。如果我们传递的索引大于数组的大小,方法会抛出一个ArgumentOutOfRangeException。

获取MessageHeader的值

当一个程序接收、解码和反序列化一个stream到Message对象的时候,我们经常需要获取一个或者多个消息头块的值。因为 MessageHeader类型提供了多种方式,我们必须求助于MessageHeaders类型。
一种方式,我们在MessageHeaders对象里获取特定的MessageHeader,就是使用索引。为了找到特定消息头块的索引,我们可以调用两个 FindHeader方法。它们都接受表示nam和namespace的String参数。其中一个方法接受一个表示能够与消息头块交互的actor的String参数。它们的返回值都是 Int32。如果没有匹配的消息头块,FindHeader回返回-1。如果找到多个消息头块,会返回第一个匹配的消息头块的索引。
备注 
我的观点,这不是一个良好的设计, 它违反了Microsoft文档里已经规定的最佳实践和关于framework设计的内部标准。它应该命名为为TryFindHeader或者如果没有找到匹配的消息头就应该抛出一个异常。抛开我的看法,当调用 FindHeader方法的时候,我们必须检查返回的值是否为-1。
在找到消息头块的索引以后(只要不是-1),我们随后就可以检查消息头块的值。为此,我们调用其中一个 GetHeader<T> 方法。重载的方法接受各种参数,包括一个消息头块的索引和一个自定义的序列化器。其中三个重载方法接受的String参数可以映射到 FindHeader方法接受的参数上。内部来看,这些重载方法调用适当的FindHeader方法,并且检查返回的值是否是-1.与FindHeader相反,如果没有找到匹配的消息头块,GetHeader<T>方法会抛出个异常。

复制一个MessageHeaders对象

MessageHeaders类型提供了几种机制从 MessageHeaders对象去复制一个或者所有的消息头块。为了看看这个功能有何用处,思考一下,当需要根据一个接受到的Message来创建一个新的Message的时候,需要什么数据。如果接受的Message包含一个PurchaseOrderInfo消息头块,我们或许需要包含一个复制的消息头块在回复的Message里。虽然可以使用相同的值重新创建一个新的消息头块,但是复制一个存在的消息头块到一个新的Message里会简单很多。
这两个CopyHeaderFrom方法提供了复制一个消息头块的值到 MessageHeaders实例里的能力。它们都接受Int32参数作为消息头块的索引。并且会把消息头块也放到内部数组的末端,没有提供指定位置的是方法。其中一个CopyHeaderFrom方法接受一个Message对象作为参数,而另外一个接受一个MessageHeaders对象作为参数。内部来看,前者通过Message类型里的Headers属性调用后者。
两个CopyHeadersFrom方法提供了复制整个 MessageHeaders对象内容的能力、同样有一个方法接受一个Message作为参数,另外一个方法接受一个MessageHeaders参数。源数据消息头块被追加到目的消息头块的尾部。换句话说,这个操作不是一个替换,而是对现有消息头块的串联。这可能有一些意外的结果,如下所示:

// create a Message创建一个消息

Message message = Message.CreateMessage(

        MessageVersion.Soap12WSAddressing10,

        “urn:SomeAction”,

        “Hello WCF”);

// add two new headers to the Message

message.Headers.To = new Uri(“http://wintellect.com/Original”);

message.Headers.Add(MessageHeader.CreateHeader(“test”, “test”, “test”));

    

// create a new Message创建一个新的消息

Message message2 = Message.CreateMessage(

        MessageVersion.Soap12WSAddressing10,

        “urn:SomeAction2”,

        “Hello WCF2”);

// add two new headers to the Message

message2.Headers.To = new Uri(“http://wintellect.com/Test”);

message2.Headers.Add(MessageHeader.CreateHeader(“test”, “test”, “test”));

    

// copy the headers from the first Message into the second one复制消息头块

message2.Headers.CopyHeadersFrom(message);

    

// show the contents

Console.WriteLine(message2.ToString());

When this code executes, the following output is generated:
执行代码,产生如下结果:

<s:Envelope xmlns:a=”http://www.w3.org/2005/08/addressing”

xmlns:s=”http://www.w3.org/2003/05/soap-envelope”>

<s:Header>

        <a:Action s:mustUnderstand=”1″>urn:SomeAction2</a:Action>

        <a:To s:mustUnderstand=”1″>http://wintellect.com/Test</a:To>

        <test xmlns=”test”>test</test>

        <a:Action s:mustUnderstand=”1″>urn:SomeAction</a:Action>

        <a:To s:mustUnderstand=”1″>http://wintellect.com/Original</a:To>

        <test xmlns=”test”>test</test>

</s:Header>

<s:Body>

        <string xmlns=”http://schemas.microsoft.com/2003/10/Serialization/”>

            Hello WCF2

        </string>

</s:Body>

</s:Envelope>

哎呦!这个Message显然不对。事实上, CopyHeaderFrom方法遇到相同的问题(重复的消息头块)。换句话说,复制消息头是件头疼的事情,开发人员需要检查目标Message里是否有重复的消息头块、

序列化一个MessageHeaders对象

MessageHeaders类型定义了几个序列化 MessageHeaders对象部分或者整体的方法。与Message和MessageHeader类型一样,MessageHeaders 类型上的序列化方法也是以单词Write开头。最简单的方法是 WriteHeader方法。如其名字暗示的一样,这个方法就是序列化一个消息头块。它接受一个Int32 和一个XmlDictionaryWriter作为参数。 Int32表示消息头块的索引,XmlDictionaryWriter,正如你猜测的一样,执行实际的序列化和编码工作。WriteHeader方法调用其它的MessageHeaders的序列化方法:WriteStartHeader和WriteHeaderContents。 WriteStartHeader方法,也和其名字暗示的一样,序列化开发的消息头块,而WriteHeaderContents方法序列化消息头块的内容。
没有一步序列化全部MessageHeaders内容的机制。唯一的方法就是迭代所有的消息头块,并序列化每一个消息头块。实际上,我们很少会有这样的需求,就是在序列化一个 Message的上下文环境外,去序列化消息头块。因此,Message类型定义了序列化真个内容的WriteMessage方法。此方法在Message类型上的实现,会迭代并序列化每一个消息头块。



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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/107968.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 用户日志管理「建议收藏」

    用户日志管理「建议收藏」摘要本发明涉及应用系统日志管理技术领域,提供了一种日志管理方法和系统,所述方法包括如下步骤:S1:初始化系统业务功能列表和业务功能方法列表;S2:将业务操作中的具体操作信息与系统日志表和历史数据日志表直接相关联;S4:根据业务操作自动记录日志信息。本发明从整体考虑整个应用系统的日志信息与业务操作挂接,用户在运行时可以根据当前的需要,选择某业务操作是否需要记录日志,并且在业务操作界面能即时将相关的日…

  • Blender权威指南「建议收藏」

    Blender权威指南「建议收藏」#Blender权威指南###第一部分基础篇####1Blender概述#####1.1开源简介######1.1.1Blender是什么######1.1.2Blender的发

  • 2021 VSCode前端插件推荐

    2021 VSCode前端插件推荐2021VSCode前端插件推荐前言推荐一波前端开发必备插件,绝对可以提高你的生产力,剩下来的时间来mo鱼,岂不美哉开发综合推荐别名路径跳转插件名:别名路径跳转使用说明:别名路径跳转插件,支持任何项目,使用场景:当你在开发页面时,想点击别名路径导入的组件时(演示如下)配置说明下载后只需自定义配置一些自己常用的别名路径即可右击插件–》扩展设置–》路径映射在settinas.json中编辑//文件名别名跳转”alias-skip.mappings”:{

  • 运维博客—OOM「建议收藏」

    运维博客—OOM「建议收藏」http://www.furion.info/649.html

  • nsga2 matlab,NSGA2算法特征选择MATLAB实现(多目标)

    nsga2 matlab,NSGA2算法特征选择MATLAB实现(多目标)利用nsga2进行进行特征选择其主要思想是:将子集的选择看作是一个搜索寻优问题(wrapper方法),生成不同的组合,对组合进行评价,再与其他的组合进行比较。这样就将子集的选择看作是一个是一个优化问题。需要优化的两个目标为特征数和精度。nsga2是一个多目标优化算法。具体的特征选择代码在上述代码的基础上改了两个①主函数②评价函数,增加了一个数据分成训练集和测试集的函数:MATLABfunction…

  • Android去掉title:windowNoTitle

    Android去掉title:windowNoTitle

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号