Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:
После завершения обработки перехваченного вызова данный перехватчик передает неизменное сообщение reqMsg следующему в цепочке перехватчику (перехватчику, находящемуся ближе к серверу). Для этого вызывается метод SyncProcessMessage перехватчика _nextSink.
После получения сообщения _replyMsg, содержащего ответ сервера (возможно обработанный перехватчиками, находящимися ближе к серверу), наш перехватчик в свою очередь обрабатывает это сообщение, если его тип
При наличии неперехваченного исключения на консоль сервера выводится соответствующее сообщение и метод возвращает полученный ответ без какой-либо обработки. В противном случае выполняется процесс, аналогичный описанному ранее (обработка вызова). Блокируется свойство контекста _property и посредством вызова метода _property.LogMessage выводится информация о типе, о вызванном методе, список выходных [out] аргументов. Ниже приведен пример для ответа на вызов метода Notify класса News:
===SPbU.AOP_NET.News, MyServer, Version = 0.0.0.0,
Culture = neutral, PublicKeyToken = null
Notify
<<<OUT>>> parameters: {
}
И, наконец, возвращается без изменений сообщение _repiyMsg.
Виртуальный метод AsyncProcessMessage объявлен в интерфейсе IMessageSink и обязательно должен быть реализован в данном классе. Этот метод предназначен для обработки асинхронных вызовов, т. е. вызовов, после инициализации которых клиент не блокируется, а продолжает свою работу.
Данный метод имеет два аргумента:
— msg — сообщение типа IMessage, содержащее вызов.
— repiysink — ссылка на перехватчик, на который надо отсылать результат. Именно этот перехватчик ответственен за уведомление клиента о полученном результате.
Атрибут MyCallTraceAttribute не предусматривает обработку асинхронных вызовов, в связи с чем при вызове данного метода генерируется исключение, уведомляющее об ошибочной операции.
? Свойство (только для чтения) NextSink также объявлено в интерфейсе IMessageSink и должно быть реализовано в данном классе. Здесь просто возвращается значение _nextsink.
Клиентское приложение
Клиентское приложение для рассматриваемого примера почти не отличается от клиентского приложения MуАрр. cs из предыдущей главы. Добавлен вывод на консоль клиента идентификатора контекста клиента, хеш потока и его тип.
using System;
using SPbU.AOP_NET;
using System.Threading;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Net;
public class MyApp {
public static void Main {
HttpChannel с = new HttpChannel;
ChannelServices.RegisterChannel(c);
try {
Console.WriteLine("Client context = " +
Thread.CurrentContext.ContextID + "\n" +
"Client thread = " +
Thread.CurrentThread.GetHashCode +
" IsPoolThread = " +
Thread.CurrentThread.IsThreadPoolThread);
Account a = (Account)Activator.GetObject {
typeof (Account),
"http://localhost:8080/Account",
WellKnownObjectMode.Singleton);
a. Add(5);
Console.WriteLine("Current account: {0}",
a. Total);
}
catch(WebException e) {
Console.WriteLine(e.Message);
}
catch(Exception e) {
Console.WriteLine(e.Message);
}
finally!
Console.WriteLine("Bye");
}
}
}
Атрибут синхронизации
Цель данного раздела состоять в частичном объяснении (в той части, которая потребуется для рассматриваемого примера) семантики атрибута SynchronizationAttribute, реализованного в .NET.
Изложение будет основано на коде, опубликованном в рамках SSCLI (файл sscli clr scr bcl system runtime remoting synchronizeddispatch.cs). Целиком этот код здесь приводиться не будет, но читателям рекомендуется самостоятельно разобраться в нем для лучшего понимания этого атрибута.
В связи с тем, что между SSCLI и .NET Framework отсутствует совместимость на уровне реализации (хотя и имеется совместимость на уровне спецификации CLI от ЕСМА), нельзя проводить какие-либо Эксперименты, заменив атрибут SynchronizationAttribute из .NET кодом из файла synchronizeddispatch.cs. Однако можно полагать, что семантика данного атрибута в .NET и в SSCLI одна и та же.
Как и в .NET, в SSCLI атрибут SynchronizationAttribute определен в пространстве имен Ssystem.Runtime.Remoting.contexts. Реализация данного атрибута представлена следующими классами:
• SynchronizationAttribute
• Workltem
• SynchronizedServerContextSink
• SynchronizedClientContextSink
• AsyncReplySink
Можно надеяться, что после знакомства С атрибутом MyCallTraceAttribute читатель догадывается о семантике почти всех из упомянутых классов. Экземпляры класса WorkItem представляют отдельные поступившие вызовы, сохраняемые в очереди работ. Синхронизация обеспечивается последовательным извлечением и выполнением работ из этой очереди.