Чтение онлайн

ЖАНРЫ

C# для профессионалов. Том II

Ватсон Карли

Шрифт:

RemotingConfiguration.RegisterWellKnownClientType(

 typeof(Hello), "tcp://localhost:8086/Hi");

Hello obj = new Hello;

Активизация объектов, активизированных клиентом

Удаленные объекты могут хранить состояние для клиента.

Activator.CreateInstance
создает активированный клиентом удаленный объект. С помощью метода
Activator.GetObject
удаленный объект создается при вызове метода и разрушается, когда метод заканчивается. Объект не хранит состояние сервера. В этом отличие от
Activator.CreateInstance
. С помощью статического метода
CreateInstance
запускается последовательность активации для создания удаленного объекта. Этот объект живет, пока не закончится время аренды и не произойдет сборка мусора. Позже мы рассмотрим механизм аренды.

Некоторые из перезагруженных методов

Activator.CreateInstance
используются только для создания локальных объектов. Для получения удаленных объектов требуется метод, куда можно передавать
activationAttributes
. Один из таких перезагруженных методов используется в примере. Этот метод получает два строковых параметра, первый из которых является именем сборки, второй — типом, а третий — массивом объектов. В объектном массиве канал и имя объекта определяются с помощью
UrlAttribute
. Чтобы использовать класс
UrlAttribute
, должно быть определено пространство имен
System.Runtime.Remoting.Activation
.

object [] attrs = { new UrlAttribute("tcp://localhost:8086/Hello") };

ObjectHandle handle =

 Activator.CreateInstance("RemoteHello",

 "Wrox.ProfessionalCSharp.Hello", attrs);

if (handle == null) {

 Console.WriteLine("could not locate server");

 return 0;

}

Hello obj = (Hello)handle.Unwrap;

Console.WriteLine(obj.Greeting("Christian"));

Конечно, для активизированных клиентом объектов также возможно использование оператора

new
вместо класса
Activator
. Таким образом, мы должны зарегистрировать активизированный клиентом объект с помощью
RemotingConfiguration.RegisterActivatedClientType
. В архитектуре активизированных клиентом объектов оператор new не только возвращает прокси, но также создает удаленный объект:

RemotingConfiguration.RegisterActivatedClientType(

 typeof (Hello), "tcp://localhost:8086/HelloServer");

Hello obj = new Hello;

Объекты прокси

Методы

Activator.GetObject
и
Activator.CreateInstance
возвращают клиенту прокси. На самом деле создается два прокси (прозрачный и реальный). Прозрачный прокси выглядит как удаленный объект, он реализует все открытые методы удаленного объекта, вызывая метод
Invoke
реального прокси. Реальный прокси посылает сообщения в канал посредством приемников сообщений.

С помощью

RemotingServices.IsTransparentProxy
проверяется, является ли объект на самом деле прозрачным прокси. Можно также добраться до реального прокси с помощью
RemotingServices.GetRealProxy
. Используя отладчик, легко получить все свойства реального прокси:

ChannelServices.RegisterChannel(new TCPChannel);

Hello obj =

 (Hello)Activator.GetObject(typeof(Hello), "tcp://localhost:8086/Hi");

if (obj == null) {

 Console.WriteLine("could not locate server");

 return 0;

}

if (RemotingServices.IsTransparentProxy(Obj)) {

 Console.WriteLine("Using a transparent proxy");

 RealProxy proxy = RemotingServices.GetRealProxy(obj);

 // proxy.Invoke(message);

}

Подключаемость
прокси

Реальный прокси может заменяться специально созданным прокси. Специально созданный прокси расширяет базовый класс

System.Runtime.Remoting.RealProxy
. Мы получаем тип удаленного объекта в конструкторе специального прокси. Вызов конструктора для
RealProxy
создает прозрачный прокси в дополнение к реальному. В конструкторе могут быть доступны зарегистрированные каналы с помощью класса
ChannelServices
для создания приемника сообщений в методе
IChannelSender.CreateMessageSink
. Помимо реализации конструктора, специальный канал переопределяет метод
Invoke
. В
Invoke
получают сообщение, которое затем анализируется и посылается в приемник сообщений.

Сообщения

Прокси посылает сообщение в канал. На серверной стороне будет сделан вызов метода после анализа сообщения, поэтому давайте рассмотрим сообщения.

Имеется несколько классов сообщений для вызова методов, ответов, возврата сообщений и т.д. Все классы сообщений должны реализовывать интерфейс

IMessage
. Этот интерфейс имеет единственное свойство:
Properties
. Это свойство представляет словарь, где
URI
указывает объект, а вызываемые
MethodName
,
MethodSignature
,
TypeName
,
Args
и
CallContext
являются пакетами.

Ниже представлена иерархия классов и интерфейсов сообщений:

Посылаемое реальному прокси сообщение является

MethodCall
. С помощью интерфейсов
IMethodCallMessage
и
IMethodMessage
мы имеем более простой доступ к свойствам сообщения, чем через интерфейс
IMessage
. Вместо использования интерфейса
IDictionary
мы имеем прямой доступ к имени метода,
URI
, аргументам и т.д. Реальный прокси возвращает
ReturnMessage
прозрачному прокси.

Приемники сообщений

Метод

Activator.GetObject
вызывает
RemotingServicesConnect
для соединения с хорошо известным объектом. В методе
Connect
происходит
Unmarshal
, где создается не только прокси, но и уполномоченные приемники. Прокси использует цепочку уполномоченных приемников для передачи сообщения в канал. Все приемники являются перехватчиками, которые могут изменять сообщение и выполнять некоторые дополнительные действия, такие как создание блокировки, запись события, выполнение проверки безопасности и т.д.

Все приемники событий реализуют интерфейс

IMessageSink
. Такой интерфейс определяет одно свойство и два метода:

□ Свойство

NextSink
используется приемником для получения следующего приемника и передачи сообщения дальше.

□ Для синхронных сообщений вызывается метод

SyncProcessMessage
предыдущим приемником или удаленной инфраструктурой. Он имеет параметр
IMessage
для отправки и возврата сообщения.

□ Для асинхронных сообщений вызывается метод

AsyncProcessMessage
предыдущим приемником в цепочке или удаленной инфраструктурой.
AsyncProcessMessage
имеет два параметра, куда могут передаваться сообщение и приемник сообщения, который получает ответ.

Поделиться с друзьями: