动态插入客户端通道接收器提供程序






4.42/5 (9投票s)
连接远程对象的所需通道的解决方法。
引言
.NET 远程处理架构以其灵活性和多功能性而闻名,
很少有局限性。
这里有一个我想指出的局限性。然后我将展示一个解决方法,利用
远程处理架构的出色灵活性,通过动态插入客户端通道接收提供程序。
问题:我有两个远程服务,名为 Knossos 和 Zakros,它们具有通道配置条目
对于 Knossos:
<channel ref="tcp" port="9000" name = "Two way binary tcp channel">
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
<serverProviders>
<formatter ref="binary"/>
</serverProviders>
</channel>
以及对于 Zakros
<channel ref="tcp" port="9000" name = "Two way soap tcp channel">
<clientProviders>
<formatter ref="soap"/>
</clientProviders>
<serverProviders>
<formatter ref="soap"/>
</serverProviders>
</channel>
请注意,两种服务的传输方式都是 TCP,但 Knossos 的格式为“binary”(二进制),而 Zakros 的格式为“soap”(SOAP)。
接下来是一个可以与 Zakros 和 Knossos 通信的客户端应用程序。以下是
客户端应用程序的通道配置:
对于 Knossos
<channel ref="tcp" port="8000" name="Two way binary client tcp channel">
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
<serverProviders>
<formatter ref="binary"/>
</serverProviders>
</channel>
以及对于 Zakros
<channel ref="tcp" port="8080" name="Two way soap client tcp channel">
<clientProviders>
<formatter ref="soap"/>
</clientProviders>
<serverProviders>
<formatter ref="soap"/>
</serverProviders>
</channel>
再次请注意,两种服务的传输方式都是 TCP,但格式为二进制和 SOAP。
有一个单独的客户端应用程序必须使用 TCP-binary 通道与 Knossos 通信,并使用 TCP-soap 通道与 Zakros 通信。这就是问题所在。与 Knossos 通过 TCP-binary 通道进行通信将正常工作。但是,与 Zakros 通过 TCP-soap 通道进行通信将无法工作。原因是远程处理系统将从注册通道列表中选择第一个 TCP 通道,而不会
考虑格式接收器。因此,与 Zakros 的连接无法工作,因为第一个 TCP 通道使用二进制格式化程序,而与 Zakros 的连接需要 SOAP 格式化程序。
如果将与 Zakros 的连接配置为 HTTP-soap 通道,一切都会正常工作。但这并不是期望的配置。
一种可能的解决方法是动态插入适当的格式化程序。我们可以通过自定义客户端接收提供程序来实现这一点。以下是类定义。
public class AbstractClientFormatterSinkProvider
: IClientFormatterSinkProvider {
public AbstractClientFormatterSinkProvider() { }
public AbstractClientFormatterSinkProvider(IDictionary props,
ICollection providerData) { }
IClientChannelSinkProvider _nextSinkProvider;
public IClientChannelSinkProvider Next {
get { return _nextSinkProvider; }
set { _nextSinkProvider = value; }
}
IClientChannelSinkProvider _transportSinkProvider;
public IClientChannelSink CreateSink(
IChannelSender channel,
String URL,
Object remoteChannelData) {
// first save the transport sink provider
if(_transportSinkProvider == null)
_transportSinkProvider = _nextSinkProvider;
String format = remoteChannelData as String;
if(format == null)
throw new Exception("Client formatter specification required.");
// create the appropriate formatter sink provider
IClientChannelSinkProvider formatterSinkProvider= null;
if(String.Compare(format,"binary", true) == 0)
formatterSinkProvider = new BinaryClientFormatterSinkProvider();
else
if(String.Compare(format,"soap", true) == 0)
formatterSinkProvider = new SoapClientFormatterSinkProvider();
else
throw new Exception("Channel data required.");
// insert it between this provider and the transport provider
formatterSinkProvider.Next = _transportSinkProvider;
_nextSinkProvider = formatterSinkProvider;
return formatterSinkProvider.CreateSink(channel, URL, null);
}
}
为了使远程处理系统接受此客户端通道接收提供程序,必须更改客户端的配置文件,如下所示
<clientProviders>
<formatter type="RemotingHelper.AbstractClientFormatterSinkProvider,
RemotingHelper"/>
</clientProviders>
这反映了程序集“RemotingHelper.dll”包含类“RemotingHelper.AbstractClientFormatterSinkProvider”
。
在客户端应用程序内部,连接到服务器 Knossos 和 Zakros 的代码如下:
String urlKnossos = "tcp://knossos:9000/KnossosObject.rem";
KnossosObject objKnossos = (KnossosObject)RemotingServices.Connect(
typeof(KnossosObject), urlKnossos, "binary");
String urlZakros = "tcp://zakros:9000/ZakrosObject.soap";
ZakrosObject objZakros = (ZakrosObject)RemotingServices.Connect(
typeof(ZakrosObject), urlZakros, "soap");
第三个参数“binary”和“soap”作为 remoteChannelData 传递给提供程序的 CreateSink 方法,提供必要的信息以动态插入适当的格式化接收提供程序。