IMessageSink Интерфейс
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Определяет интерфейс для приемника сообщений.
public interface class IMessageSink
public interface IMessageSink
[System.Runtime.InteropServices.ComVisible(true)]
public interface IMessageSink
type IMessageSink = interface
[<System.Runtime.InteropServices.ComVisible(true)>]
type IMessageSink = interface
Public Interface IMessageSink
- Производный
- Атрибуты
Примеры
В следующем примере кода показана IMessageSink реализация интерфейса . Обратите внимание, что в примере предполагается, что определения типов и ссылки на сборки должны быть предоставлены для компиляции примера.
#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 System::Security::Permissions;
using namespace Share;
public ref class MyProxy: public RealProxy
{
private:
String^ myUrl;
String^ myObjectURI;
IMessageSink^ myMessageSink;
public:
[System::Security::Permissions::PermissionSetAttribute(System::Security::Permissions::SecurityAction::LinkDemand)]
MyProxy( Type^ myType, String^ myUrl1 )
: RealProxy( myType )
{
myUrl = myUrl1;
array<IChannel^>^myRegisteredChannels = ChannelServices::RegisteredChannels;
IEnumerator^ myEnum = myRegisteredChannels->GetEnumerator();
while ( myEnum->MoveNext() )
{
IChannel^ channel = safe_cast<IChannel^>(myEnum->Current);
if ( dynamic_cast<IChannelSender^>(channel) )
{
IChannelSender^ myChannelSender = dynamic_cast<IChannelSender^>(channel);
myMessageSink = myChannelSender->CreateMessageSink( myUrl, nullptr, myObjectURI );
if ( myMessageSink != nullptr )
break;
}
}
if ( myMessageSink == nullptr )
{
throw gcnew Exception( String::Format( "A supported channel could not be found for myUrl1:{0}", myUrl ) );
}
}
virtual IMessage^ Invoke( IMessage^ myMesg ) override
{
Console::WriteLine( "MyProxy.Invoke Start" );
if ( dynamic_cast<IMethodCallMessage^>(myMesg) )
Console::WriteLine( "IMethodCallMessage" );
if ( dynamic_cast<IMethodReturnMessage^>(myMesg) )
Console::WriteLine( "IMethodReturnMessage" );
Console::WriteLine( "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( "{0} : {1}", myKeyName, myEnum->Value );
if ( myKeyName->Equals( "__Args" ) )
{
array<Object^>^myArgs = (array<Object^>^)myValue;
for ( int myInt = 0; myInt < myArgs->Length; myInt++ )
Console::WriteLine( "arg: {0} myValue: {1}", myInt, myArgs[ myInt ] );
}
if ( (myKeyName->Equals( "__MethodSignature" )) && (nullptr != myValue) )
{
array<Object^>^myArgs = (array<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->default[ "__Uri" ] = myUrl;
Console::WriteLine( "URI {0}", myDictionary->default[ "__URI" ] );
IMessage^ myRetMsg = myMessageSink->SyncProcessMessage( myMesg );
if ( dynamic_cast<IMethodReturnMessage^>(myRetMsg) )
{
IMethodReturnMessage^ myMethodReturnMessage = dynamic_cast<IMethodReturnMessage^>(myRetMsg);
}
Console::WriteLine( "MyProxy.Invoke - Finish" );
return myRetMsg;
}
};
//
// Main function that drives the whole sample
//
int main()
{
ChannelServices::RegisterChannel( gcnew HttpChannel, false );
Console::WriteLine( "Remoting Sample:" );
Console::WriteLine( "Generate a new MyProxy using the Type" );
Type^ myType = MyHelloService::typeid;
String^ myUrl1 = "http://localhost/myServiceAccess.soap";
MyProxy^ myProxy = gcnew MyProxy( myType,myUrl1 );
Console::WriteLine( "Obtain the transparent proxy from myProxy" );
MyHelloService^ myService = dynamic_cast<MyHelloService^>(myProxy->GetTransparentProxy());
Console::WriteLine( "Calling the Proxy" );
String^ myReturnString = myService->myFunction( "bill" );
Console::WriteLine( "Checking result : {0}", myReturnString );
if ( myReturnString->Equals( "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 );
}
}
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);
}
}
}
}
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)
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
<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
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
'
' 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)
Else
Console.WriteLine("myService.HelloMethod FAILED : returned {0}", myReturnString)
End If
End Sub
End Class
End Namespace 'MyNameSpace
Комментарии
При вызове метода на прокси-сервере инфраструктура удаленного взаимодействия обеспечивает необходимую поддержку для передачи аргументов фактическому объекту через границы удаленного взаимодействия, вызова метода фактического объекта с аргументами и возврата результатов клиенту прокси-объекта.
Удаленный вызов метода — это сообщение, которое отправляется от клиентской части к серверной части и, возможно, обратно. По мере того как он пересекает границы удаленного взаимодействия на пути, вызов удаленного IMessageSink
метода проходит через цепочку объектов. Каждый приемник в цепочке получает объект сообщения, выполняет определенную операцию и делегирует следующему приемнику в цепочке. Прокси-объект содержит ссылку на первый IMessageSink
объект, который необходимо использовать для запуска цепочки.
Для асинхронных вызовов во время делегирования каждый приемник предоставляет приемник ответа (другой IMessageSink
), который будет вызываться следующим приемником, когда ответ находится на обратном пути.
Различные типы приемников выполняют разные операции в зависимости от типа полученного объекта сообщения. Например, один приемник может привести к блокировке, другой может обеспечить безопасность вызовов, другой может выполнять управление вызовами и службы надежности, а другой может передавать вызов в другой AppDomainпроцесс или компьютер. Два или более приемника сообщений в цепочке могут взаимодействовать друг с другом в отношении каждого конкретного действия.
Примечания для тех, кто реализует этот метод
Важно отметить, что код, реализующий текущий интерфейс, должен предоставлять реализации для и SyncProcessMessage(IMessage)AsyncProcessMessage(IMessage, IMessageSink), так как синхронные вызовы можно преобразовать в асинхронные вызовы и наоборот. Оба метода должны быть реализованы, даже если приемник не поддерживает асинхронную обработку.
Свойства
NextSink |
Возвращает следующий приемник сообщений в цепочке приемников. |
Методы
AsyncProcessMessage(IMessage, IMessageSink) |
Асинхронно обрабатывает заданное сообщение. |
SyncProcessMessage(IMessage) |
Синхронно обрабатывает заданное сообщение. |