Описание сервера
Начнем рассмотрение с реализации сервера, находящейся в файле ChatServer.h. В архитектуре событий .NET используются делегаты с особой сигнатурой:
_delegate void JoinHandler( Object *pSender, ChatEventArg *pe); _delegate void QuitHandler( Object *pSender, ChatEventArg *pe);
Первый параметр определяет объект, посылающий сообщение о событии. Второй параметр используется для передачи данных одновременно с сообщением о событии. Обычно для хранения таких данных используется класс, производный от EventArg.
_gc class ChatEventArg: public EventArgs // класс сборщика мусора ChatEventArg: EventArgs { public: String *pName; ChatEventArg(String *pName) { pName = pName; } };
Указатель на экземпляр делегата объявляется с использованием ключевого слова _event (событие).
_gc class ChatServer // класс сборщика мусора ChatServer { public: _event JoinHandler *pJoin; _event QuitHandler *pQuit;
Обычно для упрощения вызова делегатов, связанных с обработчиком некоторого события, используют вспомогательный метод. О вызове делегата часто говорят, как о "запуске" события.
_gc class ChatServer // класс сборщика мусора ChatServer { protected: // защищенный void OnJoin(ChatEventArg *pe) { if (pJoin!= 0) { pJoin(this, pe); // запуск события } } void OnQuit(ChatEventArg *pe) { if (pQuit!= 0) { pQuitfthis, pe); // запуск события } }
Приведенный здесь вспомогательный метод проверяет, обрабатывается ли событие каким-либо экземпляром делегата. (Проверка проводится сравнением с 0.) Обычно такие вспомогательные методы объявляются как защищенные (protected), так что доступ к ним имеют только производные классы.
Теперь с помощью вызова вспомогательных методов можно запускать события.
_gc class ChatServer // класс сборщика мусора ChatServer { public: void JoinChat(String *pName) { pMembers › Add(pName); // Добавить OnJoin(new ChatEventArg(pName)); } void QuitChat(String *pName) { pMembers › Remove(pName); // Удалить OnQuitfnew ChatEventArg(pName)); }