This documentation is archived and is not being maintained.

IMessageSink Interface

Defines the interface for a message sink.

Namespace:  System.Runtime.Remoting.Messaging
Assembly:  mscorlib (in mscorlib.dll)

<ComVisibleAttribute(True)> _
Public Interface IMessageSink
Dim instance As IMessageSink

When a method call is made on the proxy, the remoting infrastructure provides the necessary support for passing the arguments to the actual object across the remoting boundaries, calling the actual object method with the arguments, and returning the results back to the client of the proxy object.

A remote method call is a message that goes from the client end to the server end and possibly back again. As it crosses remoting boundaries on the way, the remote method call passes through a chain of IMessageSink objects. Each sink in the chain receives the message object, performs a specific operation, and delegates to the next sink in the chain. The proxy object contains a reference to the first IMessageSink it needs to use to start off the chain.

For asynchronous calls, at the time of delegation, each sink provides a reply sink (another IMessageSink) that will be called by the next sink when the reply is on its way back.

Different types of sinks perform different operations, depending on the type of message object received. For example, one sink could cause a lock to be taken, another could enforce call security, another could perform flow call control and reliability services, and yet another could transport the call to a different AppDomain, process, or computer. Two or more message sinks in the chain can interact with each other in regard to each specific action.

Notes to Implementers:

It is important to note that code implementing the current interface must provide implementations for both SyncProcessMessage and AsyncProcessMessage, since synchronous calls can be converted to asynchronous calls and vice versa. Both methods must be implemented, even if the sink does not support asynchronous processing.

The following code example shows the implementation of the IMessageSink interface. Note that the sample assumes type definitions and assembly references that must be provided for the sample to compile.

Imports System
Imports System.Collections
Imports System.Threading
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting.Proxies
Imports System.Runtime.Remoting.Messaging
Imports System.Security.Permissions
Imports Share

Namespace MyNameSpace

   Public Class MyProxy
      Inherits RealProxy
      Private myUrl As String 
      Private myObjectURI As String 
      Private myMessageSink As IMessageSink

      <PermissionSet(SecurityAction.LinkDemand)> _
      Public Sub New(myType As Type, myUrl1 As String)

         myUrl = myUrl1

         Dim myRegisteredChannels As IChannel() = ChannelServices.RegisteredChannels

         Dim channel As IChannel
         For Each channel In  myRegisteredChannels
            If TypeOf channel Is IChannelSender Then 
               Dim myChannelSender As IChannelSender = CType(channel, IChannelSender)

               myMessageSink = myChannelSender.CreateMessageSink(myUrl, Nothing, myObjectURI)
               If Not (myMessageSink Is Nothing) Then 
                  Exit For 
               End If 
            End If 
         Next channel
         If myMessageSink Is Nothing Then 
            Throw New Exception("A supported channel could not be found for myUrl1:" + myUrl)
         End If 
      End Sub 'New

      <SecurityPermission(SecurityAction.LinkDemand, Flags := SecurityPermissionFlag.Infrastructure)> _
      Public Overrides Function Invoke(ByVal myMesg As IMessage) As IMessage
         Console.WriteLine("MyProxy.Invoke Start")

         If TypeOf myMesg Is IMethodCallMessage Then
         End If 
         If TypeOf myMesg Is IMethodReturnMessage Then
         End If

         Console.WriteLine("Message Properties")
         Dim myDictionary As IDictionary = myMesg.Properties
         Dim myEnum As IDictionaryEnumerator = CType(myDictionary.GetEnumerator(), IDictionaryEnumerator)

         While myEnum.MoveNext()
            Dim myKey As Object = myEnum.Key
            Dim myKeyName As String = myKey.ToString()
            Dim myValue As Object = myEnum.Value

            Console.WriteLine( "{0} : {1}", myKeyName, myEnum.Value)
            If myKeyName = "__Args" Then 
               Dim myArgs As Object() = CType(myValue, Object())
               Dim myInt As Integer 
               For myInt = 0 To myArgs.Length - 1
                  Console.WriteLine(  "arg: {0} myValue: {1}", myInt, myArgs(myInt))
               Next myInt
            End If 
            If myKeyName = "__MethodSignature" And Not (myValue Is Nothing) Then 
               Dim myArgs As Object() = CType(myValue, Object())
               Dim myInt As Integer 
               For myInt = 0 To myArgs.Length - 1
                  Console.WriteLine("arg: {0} myValue: {1}", myInt, myArgs(myInt))
               Next myInt
            End If 
         End While

         Console.WriteLine("myUrl1 {0} object URI{1}", myUrl, myObjectURI)

         myDictionary("__Uri") = myUrl
         Console.WriteLine("URI {0}", myDictionary("__URI"))

         Dim myRetMsg As IMessage = myMessageSink.SyncProcessMessage(myMesg)

         If TypeOf (myRetMsg) Is IMethodReturnMessage Then 
            Dim myMethodReturnMessage As IMethodReturnMessage = CType(myRetMsg, IMethodReturnMessage)
         End If

         Console.WriteLine("MyProxy.Invoke - Finish")
         Return myRetMsg
      End Function 'Invoke
   End Class 'MyProxy

   ' Main class that drives the whole sample 
   Public Class ProxySample
      <PermissionSet(SecurityAction.LinkDemand)> _
      Public Shared Sub Main()
         ChannelServices.RegisterChannel(New HttpChannel())

         Console.WriteLine("Remoting Sample:")

         Console.WriteLine("Generate a new MyProxy using the Type")
         Dim myType As Type = GetType(MyHelloService)
         Dim myUrl1 As String = "http://localhost/myServiceAccess.soap" 
         Dim myProxy As New MyProxy(myType, myUrl1)

         Console.WriteLine("Obtain the transparent proxy from myProxy")
         Dim myService As MyHelloService = CType(myProxy.GetTransparentProxy(), MyHelloService)

         Console.WriteLine("Calling the Proxy")
         Dim myReturnString As String = myService.myFunction("bill")

         Console.WriteLine("Checking result : {0}", myReturnString)

         If myReturnString = "Hi there bill, you are using .NET Remoting" Then
            Console.WriteLine("myService.HelloMethod PASSED : returned {0}", myReturnString)
            Console.WriteLine("myService.HelloMethod FAILED : returned {0}", myReturnString)
         End If 
      End Sub 'Main
   End Class 'ProxySample
End Namespace 'MyNameSpace
#using <mscorlib.dll>
#using <System.Runtime.Remoting.dll>
#using <System.dll>
#using <IMessageSink_Share.dll>
using namespace System;
using namespace System::Collections;
using namespace System::Threading;
using namespace System::Runtime::Remoting;
using namespace System::Runtime::Remoting::Channels;
using namespace System::Runtime::Remoting::Channels::Http;
using namespace System::Runtime::Remoting::Proxies;
using namespace System::Runtime::Remoting::Messaging;
using namespace Share;	

public __gc class MyProxy : public RealProxy
    String* myUrl;
    String* myObjectURI;
    IMessageSink* myMessageSink;

    MyProxy(Type* myType, String* myUrl1)
        : RealProxy(myType)

        myUrl = myUrl1;

        IChannel* myRegisteredChannels[] = ChannelServices::RegisteredChannels;
        IEnumerator* myEnum = myRegisteredChannels->GetEnumerator();
        while (myEnum->MoveNext())
            IChannel* channel = __try_cast<IChannel*>(myEnum->Current);
            if (dynamic_cast<IChannelSender*>(channel))
                IChannelSender* myChannelSender = dynamic_cast<IChannelSender*>(channel);

                myMessageSink = myChannelSender->CreateMessageSink(myUrl, 0, &myObjectURI);
                if (myMessageSink != 0)

        if (myMessageSink == 0)
            throw new Exception(String::Format( S"A supported channel could not be found for myUrl1:{0}", myUrl ));

    IMessage* Invoke(IMessage* myMesg)
        Console::WriteLine(S"MyProxy.Invoke Start");

        if (dynamic_cast<IMethodCallMessage*>(myMesg))

        if (dynamic_cast<IMethodReturnMessage*>(myMesg))

        Console::WriteLine(S"Message Properties");
        IDictionary* myDictionary = myMesg->Properties;
        IDictionaryEnumerator* myEnum = dynamic_cast<IDictionaryEnumerator*> (myDictionary->GetEnumerator());

        while (myEnum->MoveNext())
            Object* myKey = myEnum->Key;
            String* myKeyName = myKey->ToString();
            Object* myValue = myEnum->Value;

            Console::WriteLine(S"{0} : {1}", myKeyName, myEnum->Value);
            if (myKeyName->Equals(S"__Args"))
                Object* myArgs[] = (Object*[])myValue;
                for (int myInt = 0; myInt < myArgs->Length; myInt++)
                    Console::WriteLine(S"arg: {0} myValue: {1}", __box(myInt), myArgs[myInt]);

            if ((myKeyName->Equals(S"__MethodSignature")) && (0 != myValue))
                Object* myArgs[] = (Object*[])myValue;
                for (int myInt = 0; myInt < myArgs->Length; myInt++)
                    Console::WriteLine(S"arg: {0} myValue: {1}", __box(myInt), myArgs[myInt]);

        Console::WriteLine(S"myUrl1 {0} object URI{1}",myUrl,myObjectURI);

        myDictionary->Item[S"__Uri"] = myUrl;
        Console::WriteLine(S"URI {0}", myDictionary->Item[S"__URI"]);
        IMessage* myRetMsg = myMessageSink->SyncProcessMessage(myMesg);

        if (dynamic_cast<IMethodReturnMessage*>(myRetMsg))
            IMethodReturnMessage* myMethodReturnMessage = dynamic_cast<IMethodReturnMessage*>(myRetMsg);

        Console::WriteLine(S"MyProxy.Invoke - Finish");
        return myRetMsg;

// Main function that drives the whole sample
int main()
    ChannelServices::RegisterChannel(new HttpChannel());

    Console::WriteLine(S"Remoting Sample:");

    Console::WriteLine(S"Generate a new MyProxy using the Type");
    Type* myType = __typeof(MyHelloService);
    String* myUrl1 = S"http://localhost/myServiceAccess.soap";
    MyProxy* myProxy = new MyProxy(myType, myUrl1);

    Console::WriteLine(S"Obtain the transparent proxy from myProxy");
    MyHelloService* myService = dynamic_cast<MyHelloService*>(myProxy->GetTransparentProxy());

    Console::WriteLine(S"Calling the Proxy");
    String* myReturnString = myService->myFunction(S"bill");

    Console::WriteLine(S"Checking result : {0}", myReturnString);

    if (myReturnString->Equals(S"Hi there bill, you are using .NET Remoting"))
        Console::WriteLine(S"myService.HelloMethod PASSED : returned {0}", myReturnString);
        Console::WriteLine(S"myService.HelloMethod FAILED : returned {0}", myReturnString);

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0, 2.0, 1.1, 1.0