Click here to Skip to main content
12,293,601 members (60,426 online)
Click here to Skip to main content
Add your own
alternative version


26 bookmarked

Dynamic insertion of a client channel sink provider

, 10 Apr 2003 CPOL
Rate this:
Please Sign up or sign in to vote.
Workaround to specify a desired channel for connecting to a remote object
<!-- Add the rest of your HTML here -->


The .NET remoting architecture is world-famous for its flexibility and versatility with
limitations rarely found.

Here is one limitation that I want to point out. Then I will show a workaround, exploiting
the fabulous flexibility of the remoting architecture, by dynamically inserting a client channel sink provider.

The problem: I have two remote services named Knossos and Zakros with channel configuration entries

for Knossos: 

  <channel ref="tcp" port="9000" name = "Two way binary tcp channel">
    <formatter ref="binary"/>
    <formatter ref="binary"/>

and for Zacros:

  <channel ref="tcp" port="9000" name = "Two way soap tcp channel">
    <formatter ref="soap"/>
    <formatter ref="soap"/>

Note that the transport is TCP for either service but the formatting is 'binary' for Knossos and 'soap' for Zakros.

Next comes a client app that can communicate with both Zakros and Knossos. Here is
the channel configuration for the client app,

for Knossos:

  <channel ref="tcp" port="8000" name="Two way binary client tcp channel">
    <formatter ref="binary"/>
    <formatter ref="binary"/>

and for Zakros:

  <channel ref="tcp" port="8080" name="Two way soap client tcp channel">
    <formatter ref="soap"/>
    <formatter ref="soap"/>

Note again that the transport is TCP for either but formatting is binary and SOAP.

There is a single client app that must communicate with Knossos using the TCP-binary channel and with Zakros using the TCP-soap channel. That is the problem. The comunication with Knossos over the TCP-binary channel will work just fine. However, the communication with Zakros over the TCP-soap channel will not work. The reason for this is that the remoting system will pick the first TCP channel from the list of registered channels without
regard to the formatter sink. So, the connection to Zakros does not work because the first TCP channel uses a binary formatter whereas the connection to Zakros requires a soap formatter.

Everything would work just fine if the connection to Zakros was configured as an HTTP-soap channel. But that is not the desired configuartion.

One possible workaround is to dynamically insert the appropriate formatters. We can do this with the help of a custom client sink provider. Here is the class definition.

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();
  if(String.Compare(format,"soap", true) == 0)
   formatterSinkProvider = new SoapClientFormatterSinkProvider();
   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);

For the remoting system to accept this client channel sink provider the client's config file must be changed like so:

 <formatter type="RemotingHelper.AbstractClientFormatterSinkProvider, 

This reflects that the assembly 'RemotingHelper.dll' contains the class 'RemotingHelper.AbstractClientFormatterSinkProvider'.

And inside the client app the code connecting to the servers Knossos and Zakros is as follows:

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"); 

The third parameters 'binary' and 'soap' are passed to the provider's CreateSink method as remoteChannelData, providing the necessary information to dynamically insert the appropriate formatter sink provider.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Wytek Szymanski
Web Developer
United States United States
I am a consultant, trainer, software archtect/engineer, since the early 1980s, working in the greater area of Boston, MA, USA.

My work comprises the entire spectrum of software, shrink-wrapped applications, IT client-server, systems and protocol related work, compilers and operating systems, and more ....

I am currently focused on platform development for distributed computing in service oriented data centers.

You may also be interested in...

Comments and Discussions

QuestionHow can one contact Wytek Szymanski, the author of this arcticle? Pin
YossiMimon1-May-08 23:55
memberYossiMimon1-May-08 23:55 
Questionseveral questions about the introduced mechanism for clerification [modified] Pin
YossiMimon1-May-08 4:02
memberYossiMimon1-May-08 4:02 

When the createSink of this AbstractClientFormatterSinkProvider class is called, what is the value that placed in the field _nextSinkProvider?
What value is inside the field _transportSinkProvider and how did it get there?
This question is related to the lines:
// first save the transport sink provider
if(_transportSinkProvider == null)
_transportSinkProvider = _nextSinkProvider;
Please clerify what that save should be made.

After the AbstractClientFormatterSinkProvider.createSink is called,
it returns formatterSinkProvider.CreateSink().
So why do we keep a pointer to the formatterSinkProvider
(_nextSinkProvider = formatterSinkProvider)?
Where , when and whom are those pointers (_nextSinkProvider,formatterSinkProvider.Next) used by?

If those pointers are used, then a sink is created by the client custom class and by the formatter itself afterwards(?), so one sink is redundant.
Is that correct?

Thank you very much!

modified on Friday, May 2, 2008 5:55 AM

GeneralPerfect Pin
~Sheldon7-Aug-06 10:28
member~Sheldon7-Aug-06 10:28 
GeneralReally helpful to understand custom .NET Remoting channels Pin
Stefano Franco1-Dec-05 21:24
memberStefano Franco1-Dec-05 21:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160525.2 | Last Updated 11 Apr 2003
Article Copyright 2003 by Wytek Szymanski
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid