Ватсон Карли
Шрифт:
e.Message = "Message for Client: LongWorking Ending"; // породить событие окончания
if (Status != null) {
Console.WriteLine("RemoteObject: Firing Ending Event");
Status(this, e);
}
Console.WriteLine("RemoteObject: LongWorking Ending");
}
}
Аргументы событий
Мы видели в классе
RemoteObject
, что класс StatusEventArgs
используется как аргумент для делегата. С помощью атрибута [Serializable]
экземпляр этого класса может передаваться от сервера клиенту. Мы используем простое свойство типа string для пересылки клиенту сообщения: [Serializable]
public class StatusEventArgs {
public StatusEventArgs(string m) {
message = m;
}
public string Message {
get {
return message;
}
set {
message = value;
}
}
private string message;
}
Сервер
Сервер реализуется внутри консольного приложения. Мы ожидаем только, чтобы пользователь завершил работу сервера после чтения конфигурационного файла и настройки канала и удаленного объекта:
using System;
using System.Runtime.Remoting;
namespace Wrox.ProfessionalCSharp {
class Server {
static void Main(string[] args) {
RemotingConfiguration.Configure("Server.exe.config");
Console.WriteLine("Hit to exit");
Console.ReadLine;
}
}
}
Конфигурационный файл сервера
Способ создания конфигурационного файла сервера
Server.exe.config
мы уже обсуждали. Существует только один важный момент. Так как клиент сначала регистрирует обработчик событий и после этого вызывает удаленный метод, то удаленный объект должен сохранять состояние клиента. Можно использовать с событиями объекты SingleCall
, поэтому класс RemoteObject
конфигурируется в виде активированного клиентом типа: <configuration>
<system.runtime.remoting>
<application name="CallbackSample">
<service>
<activated type="Wrox.ProfessionalCSharp.RemoteObject, RemoteObject" />
</service>
<channels>
<channel type="System.Runtime.Remoting.Channels.Http.HttpChannel, System.Runtime.Remoting" port="6791" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
Приемник событий
Приемник событий реализует обработчик
StatusHandler
, который определен в делегате. Как ранее отмечалось, метод может иметь только входные параметры и возвращать только void
. Это в точности соответствует требованиям методов [OneWay]
, как мы видели ранее при рассмотрении асинхронной удаленной работы. StatusHandler
будет вызываться асинхронно. Класс EventSink
должен также наследовать из класса MarshalByRefObject
, чтобы сделать его удаленным, так как он будет вызывать с сервера удаленным образом: using System;
using System.Runtime.Remoting.Messaging;
namespace Wrox.ProfessionalCSharp; {
public class EventSink MarshalByRefObject {
public EventSink { }
[OneWay]
public void StatusHandler(object sender, StatusEventArgs e) {
Сonsole.WriteLine("EventSink: Event occurred: " + e.Message);
}
}
}
Клиент
Клиент читает конфигурационный файл клиента с помощью класса
RemotingConfiguration
. Так было со всеми клиентами, которые создавались до сих пор. Клиент создает локально экземпляр удаленного класса приемника EventSink
. Метод, который должен вызываться из удаленного объекта на сервере, передается в удаленный объект: using System;
using System.Runtime.Remoting;