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

ЖАНРЫ

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

Ватсон Карли

Шрифт:

Рассмотрим три доступных для использования приемника сообщения.

Уполномоченный приемник

Можно получить цепочку уполномоченных приемников с помощью интерфейса

IEnvoyInfo
. Маршализованная объектная ссылка
ObjRef
имеет свойство
EnvoyInfo
, которое возвращает интерфейс
IEnvoyInfo
. Список уполномоченных приемников создается из серверного контекста, поэтому сервер может добавлять функциональность клиенту. Уполномоченные приемники собирают информацию об идентичности клиента и предают ее серверу.

Приемник серверного контекста

Когда

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

Объектный приемник

Объектный приемник ассоциируется с определенным объектом. Если объектный класс определяет атрибуты определенного контекста, то для объекта создаются приемники контекста.

Передача объектов в удаленные методы

Типы параметров для вызовов удаленных методов не ограничены только базовыми типами данных, но могут также быть классами, которые определяет программист. Для удаленных методов различают три типа классов:

Классы, маршализуемые по значению, обычно сериализуются через канал. Классы, которые должны быть маршализованы, либо реализуют интерфейс

ISerializable
, либо помечаются с помощью атрибута
[Serializable]
. Объекты этих классов не имеют удаленной идентичности, так как весь объект маршализуется через канал, а объект, который сериализуется клиенту, является независимым от серверного объекта (или наоборот). Классы, маршализуемые по значению, называются также несвязанными классами, так как они не имеют данных, которые зависят от домена приложения.

□ Классы, маршализуемые по ссылке, имеют удаленную идентичность. Объекты не передаются по линиям связи, а вместо этого возвращается прокси. Класс, который маршализуется по ссылке, должен выводиться из

MarshalByRefObject
. Объекты
MarshalByRefObject
называют объектами, связанными с доменом приложения. Специализированной версией
MarshalByRefObject
является класс
ContextBoundObject
: абстрактный класс
ContextBoundObject
выводится из
MarshalByRefObject
. Если класс выводится из
ContextBoundObject
, требуется прокси даже в том же самом домене приложения, когда пересекаются границы контекстов.

□ Классы, которые не являются сериализуемыми и не выводятся из

MarshalByRefObject
, не могут использоваться в параметрах открытых методов удаленных объектов. Эти классы связаны с доменом приложения, где они созданы. Такие классы должны использоваться, если класс имеет члены данных, допустимые только в домене приложения, такие как дескриптор файла Win32.

Чтобы увидеть маршализацию в действии, изменим удаленный объект для пересылки двух объектов клиенту: пусть класс

MySerialized
посылает маршализацию по значению, а класс
MyRemote
маршализует по ссылке. В методах сообщение записывается на консоль, чтобы можно было проверять, сделан ли вызов на клиенте или на сервере. Кроме того, класс Hello изменяется, чтобы возвращать экземпляры
MySerilized
и
MyRemote
:

using System;

namespace Wrox.ProfessionalCSharp {

 [Serilizable]

 public сlass MySerilized {

public MySerilized(int val) {

a = val;

}

public void Foo {

Console.WriteLine("MySerialized.Foo called");

}

public int A {

get {

Console.WriteLine("MySerialized A called");

return a;

}

set {

a = value;

}

}

protected int a;

 }

 public class MyRemote : System.MarshalByRefObject {

public MyRemote(int val) {

a = val;

}

public void Foo {

Console.WriteLine("MyRemote.Foo called");

}

public int A {

get

Сonsole.WriteLine("MyRemote.A called");

return a;

}

set {

a = value;

}

}

protected int a;

 }

 /// <summary>

 /// Краткое описание Class1

 /// </summary>

 public class Hello : System.MarshalByRefObject {

public Hello {

Console.WriteLine("Constructor called");

}

~Hello {

Console.WriteLine("Destructor called");

}

public string Greeting(string name) {

Console.WriteLine("Greeting called");

return "Hello, " + name;

}

public MySerialized GetMySerilized {

return new MySerialized(4711);

}

public MyRemote GetMyRemote {

return new MyRemote(4712);

}

 }

}

Клиентское приложение также необходимо изменить, чтобы увидеть результаты при использовании маршализации объектов по значению и по ссылке. Мы вызываем методы

GetMySerialized
и
GetMyRemote
, чтобы получить новые объекты и проверить, не используется ли прозрачный прокси.

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;

}

MySerialized ser = obj.GetMySerialized;

if (!RemotingServices.IsTransparentProxy(ser)) {

 Console.WriteLine("ser is not a transparent proxy");

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