技术开发 频道

使用定制WCF MessageEncoder进行编码



【IT168 专稿】

本文将讨论一下WCF MessageEncoder的设计和它在应用开发中的角色和地位。
一、什么是MessageEncoder
    一般情况下,MessageEncoder被使用在传输通道(Channel)上,虽然MessageEncoder可以被使用在通道栈的任何地方。但MessageEncoder经常被用作进行字节转换,以克服WCF消息类在传输数据时的缺陷。

    一般来说,在通道中传输的字节是以多用途Mail扩展(MIME)格式形式存在的。对MIME的支持是一个WCF基石。WCF还可以建立基于SOAP协议进行交互的系统。事实上,WCF的功能足可以处理多种SOAP版本以及不同的XML数据格式。而MessageEncoder正在起来了在不同文件格式之间进行转换的功能。

    既然MessageEncoder支持所有被WCF支持的格式内容或协议,那么为什么要建立自己的MessageEncoder呢?

二、为什么建立自己的MessageEncoder

    我们可以假设,并不是所有通过通道传输的数据都能很好地被分类和打包。因此,建立一个用于处理这些数据的Message类可以进行一些定制的处理。定制处理可以承担对数据的加密和解密。
    建立自己的MessageEncoder的其他原因是我们可以想在整个通道栈里使用一个定制的Message类,或是当我们建立一个Message类时对这些输入数据进行转换。
    无论我们写自己的MessageEncoder类的目的是什么,我们都可以使用同样的规则和工具集。现在,我们将要实现一个MessageEncoder,并给出相应的代码供读者进行参考。


三、实例
    在本例中使用XmlDocument类打开一个XML文件,并将XmlDocument转换成字节,并从这些字节建立一个Message类,最后将Message类复制到另一个XmlDocument类。在我们看这个例子之前,有一些事情需要考虑。
    本文除了给出建立自己的MessageEncoder类的例子外,并提供了一个虚拟的案例及解决方案。 一般来讲,MessageEncoder被嵌入到一个WCF中。按着规定,一个MessageEncoder类存在于一个传输通道类中。
    现在有很多方法用于将传输过程中的字节转换为Message类。但本文的目的并不是介绍所有的工具和方法,因此,在我们深入研究代码之前先介绍一此主要的工具。
   
四、工具介绍
    在.NET中操作XML数据主要使用XmlReader和XmlWriter类。XmlReaders和XmlWriters支持各种功能,这些功能如下:

1. 可以对类分别设计它们核对一致性、包括空格、以及指定一个特殊的编码格式。
2. 读写XML数据,并可以高效地导航XML数据。
3. 从类流中读取XML。

XmlDictionalReader 和XmlDictionaryWriter类用于创建支持WCF新特性的XmlReader
和XmlWriter对象实例。
    XslCompiledTransformation是一个新的.NET2.0组件,它用于实现.NET XSLT转换功能。XSLT主要用来将一个特殊的XML文档转换为一些其他的表现形式。   
    MessageEncoder可以处理大数据量的工作。对于一个应用程序来说,分配大容量的内存空间可能成为应用程序的瓶颈。因此,WCF利用一个叫MessageBuffer的类来控制和管理预分配内存池。   
    MessageEncoder
可以和.NET流一起工作。流是一些用于操作位于不同空间(如文件系统、内存或网络)字节的类。所有的流都有一个共同的基类来完成最常用的操作。
    下面就让我们来深入研究本文提供的例子,并学习如何使用上述的工具来工作。

五、所需要的类
    象WCF中通道和其它的类一样,当我们建立一个MessageEncoder的同时,还需要建立另外两个类实例:MessageEncodingBindingElement 和MessageEncoderFactor。还有,当使用其它的WCF类时,MessageEncodingBindingElement用于处理配置,而MessageEncoderFactory用于处理创建MessageEncoder类实例。下面是TestEncoderFactory类的声明:

public class TestEncoderFactory : MessageEncoderFactory { ... }
 
    下面是TestEncoderBinding类的声明:
 
public class TestEncoderBindingElement :
   MessageEncodingBindingElement
{ ... }


    在前面的部分已经讲过,一般情况下,MessageEncoder一般用于传输通道中。而本文的例子岩石了如何在binding中合并一个MessageEncoder,并在一个传输通道中使用一个MessageEncoder。一般MessageEncoder对象实例由以下代码创建:

TestEncoderBindingElement elm = new TestEncoderBindingElement(); TestEncoderFactory factory = new TestEncoderFactory(elm); RunProgram prog = new RunProgram(); .. prog.Run(factory.Encoder);



MessageEncoder是所有继承MessageEncoder的类的基类。因此,MessageEncoder包含了很多可以覆盖的方法,如ReadMessage和WriteMessage方法。它们的功能依赖于我们希望建立的信息类型。我们可以从本文的后面部分了解到如何实现一个新的ReadMessage和WriteMessage方法。
    还有一些非常重要的可覆盖的属性和方法,用于处理"body"或Message类的数据部分,如ContentType、MediaType以及MessageVersion,它们都是关键的属性。其它的重要功能将依赖于类的具体实现。


  将字节转换为Message
    下面的代码将装载一个流,并使用一个缓冲区管理将流复制到一个缓冲区中,最后调用TestMessageEncoder中的ReadMessage方法建立一个Message类。

buffer = mgr.TakeBuffer((int)streamFrom.Length); streamFrom.Read(buffer, 0, (int)streamFrom.Length); byteArray = new ArraySegment<byte>(buffer); msg = _encoder.ReadMessage(byteArray, mgr); ReadMessage的代码如下: public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) { Message msg; XmlDocument doc = new XmlDocument(); doc.Load(stream); TestBodyWriter bw = new TestBodyWriter(doc); msg = Message.CreateMessage(this.MessageVersion,"",bw); return (msg); }

 


    看了上面的代码,也许我们的第一个问题就是ArraySegment<byte>泛型类是什么?我们可以从.NET framework文档中可以看出,ArraySegment可以和Array类一起工作,并可以对数组的部分进行包装。

    我们现在可以注意到,Message类的CreateMessage方法提供很多建立Message类的方法。对于这一点,我们可以回顾本文提供的所有重载的CreateMessage方法。接下来我们将看到如何将Message类转换回字节。
七、将Message类转换为字节
    WriteMessage方法的功能的功能复制一个Message类到一个字节流中。下面是关于WriteMessage方法的实现代码:
public override void WriteMessage(Message message, Stream stream) { XmlWriter writer = XmlWriter.Create(stream); XmlDictionaryWriter xmlDW = XmlDictionaryWriter.CreateDictionaryWriter(writer); message.WriteBodyContents(xmlDW); xmlDW.Close(); }




上面的代码是一个典型的实现。我使用了XmlDictionalWriter类将Message类的数据写到一个流中。当我们建立一个Message类实例时,Message对象被写到流中。同时OnWriteBodyContents事件被调用。在本文的开始部分,BodyWriter被XmlDocument类包装,因此,可以简单地使用XmlDocument和XmlWriter来处理Message类的内容。

八、结论

    MessageEncoder有以下几个特性。
1.  MessageEncoder将在通道中传输的字节转换为WCF Message类。
2.  MessageEncoder一般存在于传输通道中。
3.  象很多WCF类一样,MessageEncoder也有binding和工厂类。
4.  对信息编码一般使用XmlReaders、XmlWriters以及.NET framework中和流有关的类。
0
相关文章