Architecture Net или что такое Microsoft.NET?




Комната для дискуссий: пример чат-программы

Пример чат-программы EventOeTO иллюстрирует архитектуру как сервера, так и клиента В сервере реализованы следующие методы

  • JomChat,
  • QuitChat;
  • ShowMembers

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

sender = 01 Chat Room, Michael has joined the chat
sender = 01 Chat Room, BOD has -oned the chat
sender = 01 Chat Room, Sam nas ]oinea tne chat
--- After 3 nave joined---
Michael
Bob
Sam
sender = 01 Chat Room, BOD has qait the chat
--- After 1 has quit---
Michael
Sam

А вот и перевод:

отправитель = Комчата для дискуссий 01, Майкл присоединился к чату
отправитель = Комната для дискуссий 01, Боб присоединился к чату
отправителе = Коуната для дискуссий 01, Сэм присоединился к чату
---После того, как 3 присоединились---
Майкл
Боб
Сэм
отправитель = Комната дгя дискуссий 01, Боб оставил чат
---После того, как 1 покинул---
Майкл
Сэм

Исходный код клиента

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

//ChatClient.h
_gc class ChatClient
// класс сборщика мусора ChatClient
{
public:
static void OnJoinChat(Object *pSender, ChatEventArg *pe)
{
Console::WrxteLine
{
"sender = {0}, {1} has joined the chat",
// "отправитель = {0}, {1} присоединился к чату ",
pSender,
pe->pName ;
}
static void OnQuitChat(Object *pSender, ChatEventArg *pe)
{
Console::WriteLine(
"sender = 40}, {1} has quit the chat", // "отправитель = {0}, {1} покинул чат ",
pSender, pe->pName);
}
static void Main()
{
// создать сервер чата
ChatServer *pChat = new ChatServer("01 Chat Room");
// "Комната для дискуссий 01"
// Регистрация обработчиков сообщений от сервера
pChat->pJoin += new JoinHandler(pChat, OnJoinChat);
pChat->pQuit += new QuitHandler(pChat, OnQuitChat);
// вызвать методы сервера
pChat->JoinChat("Michael"); // Майкл
pChat->JoinChat/'Bob"); // Боб
pChat->JoinChat("Sam"); // Сэм
pChat->ShowMembers("After 3 have joined");
// "После того, как 3 присоединились"
pChat->QuitChat("Bob"); // Боб
pChat->ShowMembers("After 1 has quit");
// "После того, как 1 ушел"
}
};

Исходный код сервера

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

//ChatServer.h
_gc class ChatEventArg : public EventArgs
// класс сборщика мусора ChatEventArg: EventArgs
{
public:
String *pName;
ChatEventArg(String *pName)
{
this->pName = pName;
}
}; _delegate void JoinHandler(
Object *pSender, ChatEventArg *pe);
_delegate void QuitHandler(
Object *pSender, ChatEventArg *pe);
_gc class ChatServer // класс сборщика мусора ChatServer
{
private: // частный
ArrayList *pMembers;
String *pChatName;
public:
_event JoinHandler *pJoin;
_event QuitHandler *pQuit;
ChatServer(String *pChatName)
{
pMembers = new ArrayList;
this->pChatName = pChatName;
}
String *ToString ()
{
return pChatName;
}
protected: // защищенный
void OnJoin(ChatEventArg *pe)
{
if (pJoin != 0)
{
pJoin(this, pe); // запустить событие
}
}
void OnQuit(ChatEventArg *pe)
{
if (pQuit != 0)
{
pQuit(this, ре); // запустить событие
}
}
public:
void JoinChat(String *pName)
{
pMembers->Add(pName); // Добавить
OnJoin(new ChatEventArg(pName));
}
void QuitChat(String *pName)
{
pMembers->Remove(pName); // Удалить
OnQuit(new ChatEventArg(pName));
}
void ShowMembers(String *pMsg)
{
Console:rWriteLine ("—— {0} ——", pMsg);
lEnumerator *plter = pMembers->GetEnumerator();
while (p!ter->MoveNext())
{
String *pMember =
dynamic_cast<String *>((p!ter->Current)};
Console::WriteLine(pMember);
}
}
};

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