WCF技术剖析之十七:消息(Message)详解(下篇)2012-11-05 博客园 Artech《WCF技术剖析(卷1)》自出版近20天以来,得到了园子里的朋友和广大WCF爱好者的一致好评,并被卓越网计算机书店作为首页推荐,在这里对大家的支持表示感谢。同时我将一直坚持这个博文系列,与大家分享我对WCF一些感悟和学习经验。在《消息(Message)详解》系列的上篇和中篇,先后对消息版本、详细创建、状态机和基于消息的基本操作(读取、写入、拷贝、关闭)进行了深入剖析,接下来我们来谈谈消息的另一个重要组成部分:消息报头(Message Header)。按照SOAP1.1或者SOAP1.2规范,一个SOAP消息由若干SOAP报头和一个SOAP主体构成,SOAP主体是SOAP消息的有效负载,一个SOAP消息必须包含一个唯一的消息主体。SOAP报头是可选的,一个SOAP消息可以包含一个或者多个SOAP报头,SOAP报头一般用于承载一些控制信息。消息一经创建,其主体内容不能改变,而SOAP报头则可以自由地添加、修改和删除。正是因为SOAP的这种具有高度可扩展的设计,使得SOAP成为实现SOA的首选(有这么一种说法SOAP= SOA Protocol)。按照SOAP 1.2规范,一个SOAP报头集合由一系列XML元素组成,每一个报头元素的名称为Header,命名空间为http://www.w3.org/2003/05/soap-envelope。每一个报头元素可以包含任意的属性(Attribute)和子元素。在WCF中,定义了一系列类型用于表示SOAP报头。一、MessageHeaders、MessageHeaderInfo、MessageHeader和MessageHeader<T>在Message类中,消息报头集合通过只读属性Headers表示,类型为System.ServiceModel.Channels.MessageHeaders。MessageHeaders本质上就是一个System.ServiceModel.Channels.MessageHeaderInfo集合。
1: public abstract class Message : IDisposable
2: {
3: //其他成员
4: public abstract MessageHeaders Headers { get; }
5: }
1: public sealed class MessageHeaders : IEnumerable<MessageHeaderInfo>, IEnumerable
2: {
3: //省略成员
4: }
MessageHeaderInfo是一个抽象类型,是所有消息报头的基类,定义了一系列消息SOAP报头的基本属性。其中Name和Namespace分别表示报头的名称和命名空间,Actor、MustUnderstand、Reply与SOAP 1.1或者SOAP 1.2规定SOAP报头同名属性对应。需要对SOAP规范进行深入了解的读者可以从W3C官方网站下载相关文档。
1: public abstract class MessageHeaderInfo
2: {
3: protected MessageHeaderInfo();
4:
5: public abstract string Actor { get; }
6: public abstract bool IsReferenceParameter { get; }
7: public abstract bool MustUnderstand { get; }
8: public abstract string Name { get; }
9: public abstract string Namespace { get; }
10: public abstract bool Relay { get; }
11: }
当我们针对消息报头编程的时候,使用到的是另一个继承自MessageHeaderInfo的抽象类:System.ServiceModel.Channels.MessageHeader。除了实现MessageHeaderInfo定义的抽象只读属性外,MessageHeader中定义了一系列工厂方法(CreateHeader)方便开发人员创建MessageHeader对象。这些CreateHeader方法接受一个可序列化的对象,并以此作为消息报头的内容,WCF内部会负责从对象到XML InfoSet的序列化工作。此外,可以通过相应的WriteHeader方法对MessageHeader对象执行写操作。MessageHeader定义如下:
1: public abstract class MessageHeader : MessageHeaderInfo
2: {
3: public static MessageHeader CreateHeader(string name, string ns, object value);
4: public static MessageHeader CreateHeader(string name, string ns, object value, bool mustUnderstand);
5: //其他CreateHeader方法
6:
7: public void WriteHeader(XmlDictionaryWriter writer, MessageVersion messageVersion);
8: public void WriteHeader(XmlWriter writer, MessageVersion messageVersion);
9: //其他WriteHeader方法
10:
11: public override string Actor { get; }
12: public override bool IsReferenceParameter { get; }
13: public override bool MustUnderstand { get; }
14: public override bool Relay { get; }
15: }
除了MessageHeader,WCF还提供一个非常有价值的泛型类:System.ServiceModel. MessageHeader<T>,泛型参数T表示报头内容对应的类型,MessageHeader<T>为我们提供了强类型的报头创建方式。由于Message的Headers属性是一个MessageHeaderInfo的集合,MessageHeader<T>并不能直接作为Message对象的消息报头。GetUntypedHeader方法提供了从MessageHeader<T>对象到MessageHeader对象的转换。MessageHeader<T>定义如下:
1: public class MessageHeader<T>
2: {
3: public MessageHeader();
4: public MessageHeader(T content);
5: public MessageHeader(T content, bool mustUnderstand, string actor, bool relay);
6: public MessageHeader GetUntypedHeader(string name, string ns);
7:
8: public string Actor { get; set; }
9: public T Content { get; set; }
10: public bool MustUnderstand { get; set; }
11: public bool Relay { get; set; }
12: }