Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Implementing Object Pooling with .NET Remoting - Part II : Page 2

In the first part of this article series, we developed a remoting based object broker that managed pools of objects. The max and min pool size of each poolable class was defined by placing on it a custom attribute. In this second part we are going to enhance the solution to provide transparent activation of pooled objects.

Modifying Messages and Headers
In order to decide how to hook into the remoting infrastructure you have to know what and how a message body and a message header can be modified within a custom sink.

The message body holds information such as the target class and method and method’s parameter values. The header basically holds the URL remoting will use to identify the object on the server side.

The message format changes while traveling along the sinks. Before the formatter on the client side, or after the formatter on the serve side, the message is exposed to custom sinks as a .NET provided object implementing the IMessage interface. You can easily examine all the Message properties but, unfortunately, it comes out that only the method’s parameter values can be modified within a custom sink, other properties are read only.

The message is build by the Transparent proxy (an entity which can’t be overridden or customized) and the methods which would let us build a new message from scratch are defined as protected.

Of course we can do whatever we like with the message when it’s turned into its stream based form (after the formatter on the client side or before the formatter on the server side). Unfortunately in this case it’s much more difficult to modify it.

It is somehow feasible if the selected formatter is the SOAP one. If the selected channel formatter is the binary one this is practically impossible since the binary format is Microsoft proprietary.

With such limitations in mind, let’s concentrate on URL modification to trick client activation requests.

The idea is basically the following. If we put a custom sink on the server side after the formatter we can intercept the message and proceed as follow:

  • The required type is extracted from the message.

  • A check is made to see if the class is poolable (that is, if the Pooling attribute is attached to the class).

  • If it is, the Pool Manager is contacted via a shared method and asked to return an instance of the specified type from the pool.

  • A random URI (I use GUIDs) is defined and the acquired object instance is explicitly published via the RemotingServices.Marshal method using that URI.

  • The header URI property is modified to have the message request target the published object (the URI provided by the client could have been any dummy one since it’s overridden at this stage).

  • The request is forward to the next sink.

  • On return the object is disconnected from remoting (RemotingServices.Disconnect), thus providing SingleCall semantic.

Unfortunately this approach has a drawback. After .NET Framework SP2, the formatter itself checks if the specified object URI in the header is a valid one and raise an error if it’s not the case (this didn’t happen before SP2; this check was done later in the sink chain). For this reason I had to move the custom sink before the formatter. Unluckily doing this you need to modify slightly the technique described above.

Before the formatter the message is in its byte stream form, thus making hard to find out what object the client is trying to activate.

The easier way to pass this information is to define a standard for the URI format the client must specify to activate a pooled object. This format must contain the required class name and the assembly name where the class is defined.

The required format is:


In the custom sink the URI is read from the message header and the assembly and class name information are extracted from the URI string. From this point on, the steps are the same as described above.

In the step-by-step commented code listing below you can see the described technique in action:

Public Function ProcessMessage( _ ByVal sinkStack As IServerChannelSinkStack, _ ByVal requestMsg As IMessage, _ ByVal requestHeaders As ITransportHeaders, _ ByVal requestStream As Stream, _ ByRef responseMsg As IMessage, _ ByRef responseHeaders As ITransportHeaders, _ ByRef responseStream As Stream) As ServerProcessing _ Implements IServerChannelSink.ProcessMessage Dim l_objmarshalbyref As MarshalByRefObject Dim l_assembly, l_ClassName As String 'Acquires original URI Dim originalURI As String = requestHeaders.Item("__RequestUri").ToString() 'Try to extract Assembly and Class Name If IsPooledObjectURIFormat(originalURI, l_assembly, l_ClassName) = True Then

Enrico Sabbadin is a software developer (MCP) that works, since 1995, on distributed and Internet based applications design on the Microsoft platform. He is an author for several Italian programming magazines and for the ASPToday web site, and occasionally speaks at Microsoft MSDN conferences in Italy. Enrico maintains at his own site a MTS FAQ (http://www.sabbasoft.com).
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date