Welcome

首页 / 软件开发 / .NET编程技术 / 《WCF技术内幕》24:第2部分_第5章_消息:创建一个消息(上)

《WCF技术内幕》24:第2部分_第5章_消息:创建一个消息(上)2011-06-20 博客园 Frank Xu Lei创建一个消息

可以选择众多定义的CreateMessage工厂方法中的一个来创建Message对象。 绝大部分,这些方法接受的都是SOAP消息体的内容作为参数。非常重要的一点是 Message的body在创建以后就不能再做修改。SOAP消息头块,话句话说,在消息 创建以后还可以增加和修改。一般地说,Message类型的工厂方法可以根据处理 消息的路线图来划分的,从XmlReader提取数据的方法,把数据放进Message的方 法,和产生表示SOAP Fault Message的方法。在我们研究各个不同分类的工厂方 法之前,先看一些Message序列化和反序列化的上下文环境。

简要介绍Message序列化和反序列化

序列化和反序列化在分布式计算里很常见,因此,当它们牵扯到消息应用系 统的时候,就有必要弄清楚他们的意义。让我们考虑一下基本的序列化和反序列 化Message对象的步骤。放发送程序需要发送一个Message到另外一个消息参与者 的时候,它必须创建一个包含适当信息的Message 对象,然后序列化和编码 Message到一个Stream或Byte里,最后发送Stream或Byte到目的地。当接收程序 收到Message的时候,一般来说,它还是Stream或Byte状态(和发送者最后处理 的数据状态一样)。接收程序必须解码和反序列化Stream或Byte[]为 Message对 象,或许还要反序列化消息头部或者消息体为其它对象。

正如你看到的,序列化通常是与发送者规定的任务相关的,反序列化通常和 接收者的任务相关。发送者和接收者都要创建Message对象,但是发送者是内存 里的其它对象创建Message对象,而接受者是通过解码和反序列Stream 或 Byte 来创建一个Message对象。一旦接收程序解码和反序列Stream 或 Byte为一个 Message对象,它就可以转换消息的内容为一个对象,或者经过多次的对象转换 。这个转换,一般来说,也是另外一种形式的反序列化。

Message版本

因为Message对象是CLR对SOAP消息的抽象,而使用的SOAP消息有多种版本, 所以就需要考虑Message对象的表示的SOAP消息版本问题。

在Message对象模型里,SOAP消息的版本一旦在创建时设定,就无法改变。 SOAP和WS-*规范在不断的变化,因此,随着时间推移,我们应该希望这些文档版 本更新。随着它们的改变,namespace 和消息结构变化也在情理之中。为了适应 这些必然发生的变化,WCF提供了几个封装SOAP规范和WS-*规范XML消息语义的类 型。这些类型的实例会传递给工厂方法来表示Message对象的版本,Message上定 义大部分工厂方法都接受这些类型的参数。

当设置Message对象时,System.ServiceModel.Channels.EnvelopeVersion类 型代表了一个Message类型遵循的SOAP规范。同时,System.ServiceModel. Channels.AddressingVersion表示Message序列化时,消息头块遵循的WS- Addressing规范。在WCF一次发布的时候,有2个SOAP老徐备注2规范(1.1 和1.2 ),WS-Addressing规范(2004年8月,1.0)。

System.ServiceModel.Channels.MessageVersion包装了EnvelopeVersion 和 AddressingVersion类型。MessageVersion有几个static属性,它们表示 EnvelopeVersion和 AddressingVersion的几种可能的组合。下面代码显示了 MessageVersion的所有公开可见的成员:

namespace System.ServiceModel.Channels {
public sealed class MessageVersion {
public AddressingVersion Addressing { get; }
public static MessageVersion Default { get; }
public EnvelopeVersion Envelope { get; }
public static MessageVersion Soap11 { get; }
public static MessageVersion Soap12 { get; }
public static MessageVersion None { get; }
public static MessageVersion Soap11WSAddressing10 { get; }
public static MessageVersion Soap11WSAddressingAugust2004 { get; }
public static MessageVersion Soap12WSAddressing10 { get; }
public static MessageVersion Soap12WSAddressingAugust2004 { get; }
public static MessageVersion CreateVersion(
EnvelopeVersion envelopeVersion);
public static MessageVersion CreateVersion(
EnvelopeVersion envelopeVersion,
AddressingVersion addressingVersion);
public override bool Equals(object obj);
public override string ToString();
}
}

大部分成员都是可以自描述的;一些需要解释。在WCF版本3里, MessageVersion.Default返回了等价的MessageVersion.Soap12WSAddressing10 的static属性。正如你从名字里看的,这个属性表示它遵守SOAP 1.2 和WS- Addressing 1.0规范。MessageVersion.Soap11 和MessageVersion.Soap12属性 给AddressingVersion赋值为AddressingVersion.None,并且根据属性名字给 EnvelopeVersion赋值。当你想创建一个发送SOAP消息,但是不想实现WS- Addressing规范的程序时,这个非常有用。和你想的一样, MessageVersion.None对于(朴树的旧的XML)POX消息场景非常有用。