通过上篇的介绍,我们知道了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
,以便于您获取更多的相关知识。