技术开发 频道

Remoting基本原理及其扩展机制(上)

    那么.NET Remoting中又是如何创建这个Pipeline的呢?以HttpChannel为例,在创建客户端的Pipeline的时候,会调用它的CreateMessageSink方法,此时又会进一步调用HttpClientChannel的构造函数,在构造函数中调用了一个名为SetupChannel()的私有方法,看一下它的实现:
private void SetupChannel() { if (this._sinkProvider != null) { CoreChannel.AppendProviderToClientProviderChain(this._sinkProvider, new HttpClientTransportSinkProvider(this._timeout)); } else { this._sinkProvider = this.CreateDefaultClientProviderChain(); } }
     再看看在没有提供自定义SinkProvider的默认情况下CreateDefaultClientProviderChain()会创建出哪些Sink
private IClientChannelSinkProvider CreateDefaultClientProviderChain() { IClientChannelSinkProvider provider = new SoapClientFormatterSinkProvider();
provider.Next = new HttpClientTransportSinkProvider(this._timeout); return provider;
}

     其中包含了SoapClientFormatterSinkProvider与HttpClientTransportSinkProvider,自然地,到了创建Pipeline的时候,它们会分别创建出SoapClientFormatterSink与HttpClientTransportSink,前者用于实现消息对象的Soap格式化,而后者则表示将用Http协议来实现消息的通讯。这样我们就明白了为什么使用HttpChannel就会采用Http协议作为网络通讯协议,并且消息将以SOAP格式传递。但是仔细观察SetupChannel方法中的下段代码,我们可以发现通过提供自定义的SinkProvider,我们可以改变消息的编码格式,因为此时只创建了一个HttpClientTransportSinkProvider,并没有定义FormatterSinkProvider,而FormatterSinkProvider完全可以在自定义的SinkProvider中自由设定。

if (this._sinkProvider != null) { CoreChannel.AppendProviderToClientProviderChain(this._sinkProvider, new HttpClientTransportSinkProvider(this._timeout)); }

    那么我们又如何在.NET Remoting中定义自己的SinkProvider并让它发挥作用呢?下面这幅图演示如果使用自定义SinkProvider对Pipeline进行定制。

 

    首先在配置文件中引用自定义的ChannelSinkProvider的类名及其所在程序集,然后编写自定义的ChannelSinkProvider的具体实现,也就是加入你需要的ChannelSink,最后在自定义的ChannelSink中实现具体的处理操作。这样我们向Pipeline中成功地添加了自定义处理模块。这里需要提醒大家注意,接收方的Pipeline信道与发送方Pipeline之间存在着一个根本的差异。发送方Pipeline为每个远程对象的真实代理创建一个接收器(Sink)链。接收方信道在其创建之时创建了接收器(Sink)链,这条链将为所有通过这个接收方Pipeline进行转送的调用所使用,不论与这个调用相关联的对象是哪个。下图展示了这个差异:

    细心的读者可能已经注意到之前我们定制的是ChannelSink,为什么要加上一个Channel呢?让我们回过头去再看看图1,其中有两个绿色的Sink,他们都是Remoting中可选的组件,也是我们对Pipeline进行扩展的地方。你可以在这两个地方加入自定义的Sink,从而对流经Pipeline的数据做某些需要的处理,前者需实现IMessageSink接口,后者需要实现IXXXChannelSink接口,那么它们又有何不同呢?注意看图1,我们会发现其中隔了一个Formmatter Sink,而Formmatter Sink的作用就是将原来的.NET消息变成可在网络上传播的数据流(可以是Binary或Soap格式),这也就表明前者的输入是消息对象,而后者的输入是数据流(Stream)。这也就决定了他们各自所能实现的扩展功能是不同的。比如,操作消息对象,我们可以把远程方法的参数变一变(比如从英文翻成中文),而操作数据流,我们可以实现数据流的加密或压缩之类功能。如何定制新的ChannelSink并将其加入到Pipeline中已经在图2中演示过了,那么MessageSink呢?

0
相关文章