Удаленные объекты могут хранить состояние для клиента.
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 не только возвращает прокси, но также создает удаленный объект:
возвращают клиенту прокси. На самом деле создается два прокси (прозрачный и реальный). Прозрачный прокси выглядит как удаленный объект, он реализует все открытые методы удаленного объекта, вызывая метод
Invoke
реального прокси. Реальный прокси посылает сообщения в канал посредством приемников сообщений.
С помощью
RemotingServices.IsTransparentProxy
проверяется, является ли объект на самом деле прозрачным прокси. Можно также добраться до реального прокси с помощью
RemotingServices.GetRealProxy
. Используя отладчик, легко получить все свойства реального прокси:
Реальный прокси может заменяться специально созданным прокси. Специально созданный прокси расширяет базовый класс
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
имеет два параметра, куда могут передаваться сообщение и приемник сообщения, который получает ответ.