WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇)

通过上篇的介绍,我们知道了WCF所有与编码与解码相关的功能都实现在相应的System.Xml.XmlDictionaryWriter和System.Xml.XmlDictionaryReader中。但是在真正的WCF处理框架中,却并不直接使用XmlDictioanryWriter和XmlDictionaryReader对象,而通过相应的消息编码器(System.ServiceModel.Channels.MessageEncoder)对其进行进一步封装,专门用于消息的编码和解码。

一、消息编码器(MessageEncoder)

消息编码器通过类型MessageEncoder表示,MessageEncoder是定义在System.ServiceModel.Channels命名空间下的一个抽象类。从下面的定义中可以看出,MessageEncoder主要包含两种类型的操作:读消息和写消息,分别通过ReaderMessage和WriteMessage方法实现。此外,两个额外的方法,GetProperty<T>用于获取MessageEncoder相关的一些属性,IsContentTypeSupported用于判断MessageEncoder是否支持某种类型的MIME类型。

   1: public abstract class MessageEncoder   2: {   3:     //其他成员   4:     public virtual T GetProperty<T>() where T : class;   5:     public virtual bool IsContentTypeSupported(string contentType);   6:   7:     public Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager);   8:     public Message ReadMessage(Stream stream, int maxSizeOfHeaders);   9:     public abstract Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType);  10:     public abstract Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType);  11:  12:     public abstract void WriteMessage(Message message, Stream stream);  13:     public ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager);  14:     public abstract ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset);  15:  16:     public abstract string ContentType { get; }  17:     public abstract string MediaType { get; }  18:     public abstract MessageVersion MessageVersion { get; }  19: }

与上面介绍的3种类型的XmlDictionaryWriter/XmlDictionaryReader相对应,WCF同样定义了MessageEncoder:TextMessageEncoder、BinaryMessageEncoder和MtomMessageEncoder三种MessageEncoder,它们分别封装了XmlUTF8TextWriter/XmlUTF8TextReader、XmlBinaryWriter/XmlBinaryReader和XmlMtomWriter/XmlMtomReader。WCF定义了3个相应的工厂类:TextMessageEncoderFactory、BinaryMessageEncoderFactory和MtomMessageEncoderFactory用于创建相应的MessageEncoder。它们共同继承一个抽象类:System.ServiceModel.Channels.MessageEncoderFactory。通过只读属性Encoder得到相应的MessageEncoder。

   1: public abstract class MessageEncoderFactory   2: {   3:     //其他成员   4:     public abstract MessageEncoder Encoder { get; }   5: }

二、 实例演示通过MessageCoder对消息进行编码

接下来,我们来演示一个实例:如何通过MessageCoder对一个具体的Message对象进行编码。本例主要演示TextMessageCoder和MtomMessageEncoder编码方式的对比。此外,为了演示MTOM对二进制数据的编码优化,我们创建一个基于二进制内容的Message对象,并将一个位图作为消息的主体。

我们先创建如下一个静态辅助方法WriteMessage,该方法通过MessageEncoderFactory得到的MessageEncoder对象将Message对象写入一个文件中。

   1: static void WriteMessage(MessageEncoderFactory encoderFactory, Message message, string fileName)   2: {   3:     using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Write))   4:     {   5:         encoderFactory.Encoder.WriteMessage(message, stream);   6:     }   7: }

如果调用上面的方法,首先需要创建MessageEncoderFactory对象。由于TextMessageEncoderFactory和MtomMessageEncoderFactory是一个内部类型,不能直接实例化,所以只能通过反射的机制创建两个MessageEncoder。下面是TextMessageEncoder和MtomMessageEncoderFactory构造函数的定义。

   1: internal class TextMessageEncoderFactory : MessageEncoderFactory   2: {   3:     //其他成员   4:     public TextMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas);   5: }   6: internal class MtomMessageEncoderFactory : MessageEncoderFactory   7: {   8:     //其他成员   9:     public MtomMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas);  10: }

在下面的代码中,先通过Message的静态方法CreateMessage创建Message对象,需要注意的第3个参数是一个表示位图的Bitmap对象。然后通过反射创建TextMessageEncoderFactory和MtomMessageEncoderFactory对象,并调用上面定义的辅助方法WriteMessage。

   1: Message message = Message.CreateMessage(MessageVersion.Default, "http://www.artech.com/myaction", new Bitmap(@"C:\Users\Jinnan\Pictures\photo.jpg"));   2: MessageBuffer buffer = message.CreateBufferedCopy(int.MaxValue);   3:   4: //通过反射创建TextMessageEncoderFactory   5: string encoderFactoryType = "System.ServiceModel.Channels.TextMessageEncoderFactory,System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";   6: MessageEncoderFactory encoderFactory = (MessageEncoderFactory)Activator.CreateInstance(Type.GetType(encoderFactoryType), MessageVersion.Default, Encoding.UTF8, int.MaxValue, int.MaxValue, new XmlDictionaryReaderQuotas());   7:   8: WriteMessage(encoderFactory, buffer.CreateMessage(), @"E:\message.text.xml");    9:  10: //通过反射创建MtomMessageEncoderFactory  11: encoderFactoryType = "System.ServiceModel.Channels.MtomMessageEncoderFactory,System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";  12: encoderFactory = (MessageEncoderFactory)Activator.CreateInstance(Type.GetType(encoderFactoryType), MessageVersion.Default, Encoding.UTF8, int.MaxValue, int.MaxValue, int.MaxValue, new XmlDictionaryReaderQuotas());  13:  14: WriteMessage(encoderFactory, buffer.CreateMessage(), @"E:\message.mtom.xml");

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索对象
, public
, abstract
, message
, 解码时如何设置buffer
编码entity文档xmlutf-8
,以便于您获取更多的相关知识。

时间: 2024-08-18 03:22:46

WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇)的相关文章

WCF技术剖析系列文章汇总

WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇] WCF技术剖析之三十:一个很有用的WCF调用编程技巧[上篇] WCF技术剖析之二十九:换种不同的方式调用WCF服务 WCF技术剖析之二十八:自己动手获取元数据 WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的 WCF技术剖析之二十七: 如何将一个服务发布成WSDL WCF技术剖析之二十七: 如何将一个服务发布成WSDL[编程篇] WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展

《WCF技术内幕》翻译9:第1部分_第2章_面向服务:消息编码

消息编码 随着时间的流逝,也许我们会条件反射式地认为XML(SOAP)是一个结构文本 .毕竟,文本是人可读的,每个计算机系统也可以处理文本.基于文本的XML的 普遍共性与我们的与其它系统交互的想法产生了共鸣.可以容易的解释的基于文 本的XML本质上会体积变大.可以理解使用XML会带来性能损失.就像要花费点精 力把信装到信封里一样,它需要一些处理时间与XML交互.某些情况下,基于文 本的XML数据大小限制了它的应用,特别是当我们要通过网络发送一个XML消息的 时候. 此外,如果我们限制自己使用基于

WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用

原文:WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML.反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该如何实现这样的场景? 比如下面定义了两个类型Contact和Customer,

WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)

原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]大部分的系统都是以数据为中心的(Data Central),功能的实现表现在对相关数据的正确处理.而数据本身,是有效信息的载体,在不同的环境具有不同的表示.一个分布式的互联系统关注于数据的交换,而数据正常交换的根本前提是参与数据交换的双方对于数据结

WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇]

在<上篇>中,我通过使用Delegate的方式解决了服务调用过程中的异常处理以及对服务代理的关闭.对于<WCF技术剖析(卷1)>的读者,应该会知道在第7章中我通过类似于AOP的方式解决了相似的问题,现在我们来讨论这个解决方案. 通过<服务代理不能得到及时关闭会有什么后果?>的介绍,我们知道了及时关闭服务代理的重要意义,并且给出了正确的编程方式.如果严格按照上面的编程方式,就意味着对于每一个服务调用,都要使用相同的代码进行异常处理和关闭或中断服务代理对象.按照我个人的观点

WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇]

通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding元素来源于终结点的绑定对象,那么这些基于Binding的元数据以及相应的策略断言是如何被写入WSDL的呢?WSDL导出扩展(WSDL Export Extension)和策略导出扩展(Policy Export Extension)就是为此设计的. 一.WSDL导出扩展(WSDL Export Extension) 终结点的绑定本质上就是相关的绑定元素(BindingElement)的有序组合(

WCF技术剖析之二十五:元数据(Metadata)架构体系全景展现[WS标准篇]

元数据实际上是服务终结点的描述,终结点由地址(Address).绑定(Binding)和契约(Contract)经典的ABC三要素组成.认真阅读过<WCF技术剖析(卷1)>的读者相对会对这三要素的本质有一个深刻的认识:地址决定了服务的位置并实现相应的寻址机制:契约描述了消息交换模式(Message Exchange Pattern: MEP)以及消息的结构(Schema):绑定则通过创建信道栈实现对消息的编码.传输和基于某些特殊的功能(比如实现事务.可靠传输以及基于消息的安全)对消息作出的处理

WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[下篇]

WCF客户端和服务端的框架体系相互协作,使得开发人员可以按照我们熟悉的方式进行异常的处理:在服务操作执行过程中抛出异常(FaultException),在调用服务时捕获异常,完全感觉不到"分布式"的存在,如同典型的"本地"操作一般.为了实现这样的效果,WCF在内部为我们作了很多. 消息交换是WCF进行通信的唯一手段,消息不仅仅是正常服务调用请求和回复的载体,服务端抛出的异常,甚至是服务的元数据都是通过消息的形式传向客户端的.所以,实现异常与消息之间的转换是整个异常处

WCF技术剖析之十二

数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) 大部分的系统都是以数据为中心的(Data Central),功能的实现表现在对相关数据的正确处理.而数据本身,是有效信息的载体,在不同的环境具有不同的表示.一个分布式的互联系统关注于数据的交换,而数据正常交换的根本前提是参与数据交换的双方对于数据结构的一致性理解.这就为数据的表现提出了要求,为了保证处于不同平台.不同厂商的应用能够正常地进行数据交换,交换的数据必须采用一种大家都能够理解的展现