IMessageSink Interface
Defines the interface for a message sink.
For a list of all members of this type, see IMessageSink Members.
[Visual Basic] Public Interface IMessageSink [C#] public interface IMessageSink [C++] public __gc __interface IMessageSink [JScript] public interface IMessageSink
Classes that Implement IMessageSink
| Class | Description |
|---|---|
| AsyncResult | Encapsulates the results of an asynchronous operation on an asynchronous delegate. |
| BinaryClientFormatterSink | Provides the implementation for a client formatter sink that uses the BinaryFormatter. |
| SoapClientFormatterSink | Provides the implementation for a client formatter sink that uses the SoapFormatter. |
Remarks
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.
Example
[Visual Basic] 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 Share Namespace MyNameSpace Public Class MyProxy Inherits RealProxy Private myUrl As String Private myObjectURI As String Private myMessageSink As IMessageSink Public Sub New(myType As Type, myUrl1 As String) MyBase.New(myType) 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 Public Overrides Function Invoke(ByVal myMesg As IMessage) As IMessage Console.WriteLine("MyProxy.Invoke Start") If TypeOf myMesg Is IMethodCallMessage Then Console.WriteLine("IMethodCallMessage") End If If TypeOf myMesg Is IMethodReturnMessage Then Console.WriteLine("IMethodReturnMessage") 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 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) Else Console.WriteLine("myService.HelloMethod FAILED : returned {0}", myReturnString) End If End Sub 'Main End Class 'ProxySample End Namespace 'MyNameSpace [C#] using System; using System.Collections; using System.Threading; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Proxies; using System.Runtime.Remoting.Messaging; using Share; namespace MyNameSpace { public class MyProxy : RealProxy { string myUrl; string myObjectURI; IMessageSink myMessageSink; public MyProxy(Type myType, string myUrl1) : base(myType) { myUrl = myUrl1; IChannel[] myRegisteredChannels = ChannelServices.RegisteredChannels; foreach (IChannel channel in myRegisteredChannels ) { if (channel is IChannelSender) { IChannelSender myChannelSender = (IChannelSender)channel; myMessageSink = myChannelSender.CreateMessageSink(myUrl, null, out myObjectURI); if (myMessageSink != null) break; } } if (myMessageSink == null) { throw new Exception("A supported channel could not be found for myUrl1:"+ myUrl); } } public override IMessage Invoke(IMessage myMesg) { Console.WriteLine("MyProxy.Invoke Start"); if (myMesg is IMethodCallMessage) Console.WriteLine("IMethodCallMessage"); if (myMesg is IMethodReturnMessage) Console.WriteLine("IMethodReturnMessage"); Console.WriteLine("Message Properties"); IDictionary myDictionary = myMesg.Properties; IDictionaryEnumerator myEnum = (IDictionaryEnumerator) myDictionary.GetEnumerator(); while (myEnum.MoveNext()) { object myKey = myEnum.Key; string myKeyName = myKey.ToString(); object myValue = myEnum.Value; Console.WriteLine("{0} : {1}", myKeyName, myEnum.Value); if (myKeyName == "__Args") { object[] myArgs = (object[])myValue; for (int myInt = 0; myInt < myArgs.Length; myInt++) Console.WriteLine("arg: {0} myValue: {1}", myInt, myArgs[myInt]); } if ((myKeyName == "__MethodSignature") && (null != myValue)) { object[] myArgs = (object[])myValue; for (int myInt = 0; myInt < myArgs.Length; myInt++) Console.WriteLine("arg: {0} myValue: {1}", myInt, myArgs[myInt]); } } Console.WriteLine("myUrl1 {0} object URI{1}",myUrl,myObjectURI); myDictionary["__Uri"] = myUrl; Console.WriteLine("URI {0}", myDictionary["__URI"]); IMessage myRetMsg = myMessageSink.SyncProcessMessage(myMesg); if (myRetMsg is IMethodReturnMessage) { IMethodReturnMessage myMethodReturnMessage = (IMethodReturnMessage)myRetMsg; } Console.WriteLine("MyProxy.Invoke - Finish"); return myRetMsg; } } // // Main class that drives the whole sample // public class ProxySample { public static void Main() { ChannelServices.RegisterChannel(new HttpChannel()); Console.WriteLine("Remoting Sample:"); Console.WriteLine("Generate a new MyProxy using the Type"); Type myType = typeof(MyHelloService); string myUrl1 = "http://localhost/myServiceAccess.soap"; MyProxy myProxy = new MyProxy(myType, myUrl1); Console.WriteLine("Obtain the transparent proxy from myProxy"); MyHelloService myService = (MyHelloService)myProxy.GetTransparentProxy(); Console.WriteLine("Calling the Proxy"); string myReturnString = myService.myFunction("bill"); Console.WriteLine("Checking result : {0}", myReturnString); if (myReturnString == "Hi there bill, you are using .NET Remoting") { Console.WriteLine("myService.HelloMethod PASSED : returned {0}", myReturnString); } else { Console.WriteLine("myService.HelloMethod FAILED : returned {0}", myReturnString); } } } } [C++] #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; public: 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) break; } } 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)) Console::WriteLine(S"IMethodCallMessage"); if (dynamic_cast<IMethodReturnMessage*>(myMesg)) Console::WriteLine(S"IMethodReturnMessage"); 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); } else { Console::WriteLine(S"myService.HelloMethod FAILED : returned {0}", myReturnString); } }
[JScript] No example is available for JScript. To view a Visual Basic, C#, or C++ example, click the Language Filter button
in the upper-left corner of the page.
Requirements
Namespace: System.Runtime.Remoting.Messaging
Platforms: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 family
Assembly: Mscorlib (in Mscorlib.dll)
See Also
IMessageSink Members | System.Runtime.Remoting.Messaging Namespace