Промежуточная среда .NET Remoting
Конструктор клиентской трубы канала должен создать клиента MSMQ для передачи сообщений.
public MsmqClientChannelSink(string remoteObjectUri)
{
// выделение из URL пути к очереди и адреса объекта
queuePath = Utils.ParseUrl(remoteObjectUri, out objectUri);
// создание клиента MSMQ, не ожидающего ответов от сервера
// и использующего бинарный класс форматирования
msmqClient = new MsmqClient<IMessage, IMessage>(queuePath, null,
QueueFormatter.Binary);
}
public IMessage SyncProcessMessage(IMessage msg)
{
throw new NotSupportedException(
"Поддерживаются только методы с OneWayAttribute.");
}Метод AsyncProcessMessage используется для реализации асинхронного вызова. В данном примере он должен передать сообщение Remoting клиенту MSMQ.
public IMessageCtrl AsyncProcessMessage(IMessage message,
IMessageSink replySink)
{
// свойство сообщения c адресом удаленного объекта
message.Properties[MessageProperties.ObjectUri] = objectUri;
// передача сообщения клиенту MSMQ для его отсылки серверу
msmqClient.Send(message);
return null;
}
// данная труба - первая и последняя в цепочке
public IMessageSink NextSink
{
get { return null; }
}
} // Seva.Remoting.MsmqChannel.MsmqClientChannelSinkПринимающая сторона состоит из канала MsmqChannelReceiver.
public class MsmqChannelReceiver: MsmqBase, IChannelReceiver
{
// Класс-сервер MSMQ для приема сообщений Remoting
private MsmqServer<IMessage, IMessage> msmqServer;
// Серверная труба канала
private IServerChannelSink sink;
// Стек труб на стороне сервера
private ServerChannelSinkStack stack;
// необходимое для реализации интерфейса свойство
public object ChannelData
{
get { return null; }
}Десериализация сообщения осуществляется в классе MsmqServer, поэтому цепочка труб сервера состоит только из стандартной трубы диспетчеризации. Для вызова метода ProcessMessage трубы диспетчеризации создается стек труб. Сервер ожидает сообщения из очереди, указанной в файле конфигурации.
public MsmqChannelReceiver(IDictionary properties,
IServerChannelSinkProvider serverSinkProvider)
{
// создать сервер MSMQ
msmqServer = new MsmqServer<IMessage, IMessage>(
properties["queue"].ToString(), QueueFormatter.Binary);
msmqServer.ProcessMessage += OnReceive;
if (serverSinkProvider!=null)
{
throw new NotSupportedException(
"Поставщики не поддерживаются.");
}Поскольку начальной обработкой пришедших сообщений занимается класс MsmqReceiver, а десериализацией – класс MsmqServer, то в конструкторе достаточно создать стандартную трубу диспетчеризации сообщений на сервере.
sink = ChannelServices.CreateServerChannelSinkChain(null, this);
// создание стека труб
stack = new ServerChannelSinkStack();
stack.Push(sink, null);
// Начать ожидание собщений в очереди
StartListening(null);
}
// метод интерфейса IChannelReceiver, возваращает все URL для данного URI
public virtual string[] GetUrlsForUri(string objectURI)
{
return new string[] {objectURI};
}
// обработка пришедшего сообщения MSMQ
private IMessage OnReceive(Object sender, IMessage request,
MessageQueue queueResponse)
{
return ProcessMessage(request);
}
// методы, управляющие прослушивание канала
public void StartListening(Object data)
{
msmqServer.BeginReceive();
}
public void StopListening(Object data)
{
msmqServer.EndReceive();
}
Листинг
8.5.
Метод ProcessMessage обрабатывает пришедшее сообщение .NET Remoting. В данном классе достаточно передать его дальше в трубу канала для передачи, в итоге, диспетчеру сообщений Remoting.
private IMessage ProcessMessage(IMessage request)
{
IMessage response = null;
// если в сообщении не указан URI объекта, то ничего не делать
object uri = request.Properties[MessageProperties.ObjectUri];
if (uri == null) return null;
string url = uri.ToString();
// Необходимо заполнить свойство сообщения __URI
request.Properties[MessageProperties.Uri] = uri;
// Передача сообщения в трубу канала
Stream responseStream = null;
ITransportHeaders responseHeaders = null;
sink.ProcessMessage(stack, request, null, null,
out response, out responseHeaders, out responseStream);
return response;
}
} // Seva.Remoting.MsmqChannel.MsmqReceiver