- •107 Методические указания «Программное обеспечение сетей эвм. Часть 4. Версия 2. Развитие схемы «клиент-сервер» в com и corba»
- •Введение
- •1.1. Необходимость использования компонент
- •1.2. Методы встраивания компонентов
- •1.3. Основы com
- •1.4. Типы компонентов
- •1.5. Размещение управляющих элементов при помощи cWnd
- •1.6. Использование директивы #import
- •1.7. Компоновка тестовой программы
- •1.7.1 О компонентах
- •1.7.2 Регистрация компонентов
- •1.7.3 Импортирование библиотеки типов
- •1.7.4 Определение членов cDemoClientView
- •1.7.5 Создание компонентов
- •1.7.6 Создание точек взаимодействия
- •1.7.7 Синхронизация параметров
- •1.7.8 Обработка событий от компонентов
- •1.7.9 Очистка
- •1.7.10 Шаблонный код
- •1.9. Индивидуальные задания на работу
- •2.1. Проект. Основные принципы
- •2.2. Как создать компонент
- •Шаг 2: Создание компонента:
- •2.3. Значения по умолчанию
- •2.5. Индивидуальные задания на работу
- •3.1. Cоздание сервера com
- •3.2. Использование com-объектов
- •3.3. Индивидуальные задания на работу
- •Лабораторная работа № 4. Использование atl
- •4.1 Создание dcom-сервера с использованием atl
- •4.1.1 Введение в atl
- •4.1.2 Что такое atl?
- •4.1.3 Разделение труда
- •4.1.4 Создание хранилища компонентов с помощью atl Com AppWizard
- •4.1.5 Вставка кода заглушки/прокси-объекта.
- •4.1.7 Atl com-карта
- •4.1.9 Класс cComModule
- •4.1.10 Язык скриптов реестра в atl
- •4.1.11 Распределенная com (dcom)
- •4.1.12 Dcom и службы nt
- •4.1.13 Структура службы nt
- •4.1.14 Основанный на службах nt сервер сом
- •4.1.15 Создание проекта при помощи atl
- •4.1.16 Добавление функциональных средств
- •4.1.17 Функция CacheQuotes (dcomServiceXdcomService.Cpp)
- •4.1.18 Функция GetQuote (dcomServiceXdcomService.Cpp)
- •4.2 Создание dcom сервера
- •4.3 Создание dcom клиента
- •4.4 Индивидуальные задания на работу
- •Лабораторная работа № 5. Разработка corba приложений
- •5.1. Конфигурирование
- •5.2. Порядок действий
- •5.3. Объектно-ориентированный анализ и моделирование
- •5.4. Описание и трансляция объектов
- •5.5. Создание сервера
- •5.6. Создание клиента
- •5.7. Отладка объектов
- •5.8. Индивидуальные задания на работу
- •Лабораторная работа № 6. Адаптер роа
- •6.1. Архитектура poa
- •6.2. Политики poa
- •Политика обработки запросов
- •6.3. Создание серверов на основе poa
- •6.4. Индивидуальные задания на работу
- •Лабораторная работа № 7. Прикладная задача связи
- •7.1. Постановка задачи
- •7.1.1. Сотовая станция
- •7.1.2. Телефоны
- •7.1.3. Система
- •7.2. Функционирование системы
- •7.3. Индивидуальные задания на работу
- •Лабораторная работа № 8. Работа по умолчанию
- •8.1. Сервер с сервантом по умолчанию
- •8.2. Индивидуальные задания на работу
- •Лабораторная работа № 9. Создание менеджеров сервантов
- •9.1. Менеджеры сервантов
- •ServantActivator
- •ServantLocator
- •9.2. И снова практика
- •9.3. Индивидуальные задания на работу
- •Лабораторная работа № 10. Сервис именования
- •10.1. Сервис для именования (Naming Service)
- •10.2. Индивидуальные задания на работу
1.7.6 Создание точек взаимодействия
Как отмечалось, точки взаимодействия можно использовать для уведомления компонентом клиента о наступлении некоторых событий или запроса к клиенту на выполнение некоторых действий. Однако их можно использовать и для обеспечения взаимодействия между двумя компонентами в одном или разных контейнерах.
Компонент, предоставляющий точки взаимодействия, должен иметь интерфейс IConnectionPointContainer. В своей реализации этого интерфейса компонент указывает, какой именно интерфейс является интерфейсом точек взаимодействия. Клиент должен создать реализацию этого интерфейса и передать компоненту ссылку на эту реализацию. После этого компонент может вызывать методы интерфейса точек взаимодействия. Для реализации интерфейса взаимодействия клиент должен знать, какие методы и свойства этот интерфейс предоставляет. Обычно клиенту доступна эта информация, поскольку компонент определяет интерфейс точек взаимодействия в своей библиотеке типов. Разработчик клиента обычно пользуется этой информацией для того, чтобы определить, какие методы и свойства он должен реализовать для использования точек взаимодействия.
Первая точка взаимодействия, которая будет использоваться - интерфейс IDemoModelConnection. Он определен в компоненте DemoModel и является исходящим управляющим интерфейсом, при помощи которого компонент-модель может напрямую управлять компонентом представления. Управляющий элемент DemoView создает реализацию этого интерфейса, после чего компонент DemoModel может вызывать методы этого интерфейса. По отношению к общему описанию точек взаимодействия DemoView является клиентом, а DemoModel - компонентом. Следующий код показывает, как подключаются точки взаимодействия:
// создание точки взаимодействия между представлением и моделью
IConnectionPointContainerPtr pCPC = m_pModel;
IUnknownPtr pUnk = m_pView;
if (pCPC != NULL)
{
pCPC->FindConnectionPoint(__uuidof(IDemoModelConnection), &m_pCP);
if (m_pCP != NULL)
{
m_pCP->Advise(pUnk, &m_dwCookie);
}
}
Здесь снова использован оператор связывания класса-оболочки для непосредственного вызова QueryInterface() для интерфейса IConnectionPointContainer. То же самое сделано для получения указателя IUnknown на управляющий элемент представления. При успешном завершении вызывается метод FindConnectionPoint() интерфейса IConnectionPointContainer для компонента модели чтобы узнать, поддерживает ли он интерфейс точек взаимодействия IDemoModelConnection. Если это так, то указатель IUnknown передается компоненту представления, а в ответ принимается значение ключа для этого взаимодействия. После установки взаимодействия компонент DemoModel может вызывать любой метод интерфейса IDemoModelConnection компонента представления. Если заглянуть в код компонента, то видно, что модель создает таймер и периодически вызывает метод Update() для обновления угла поворота представления согласно новым показаниям скорости и времени.
1.7.7 Синхронизация параметров
Последнее, что осталось сделать - синхронизировать параметры компонента управления с компонентами представления и модели. Для этого нужно ввести изменения в функцию OnInitialUpdate():
// инициализация параметров компонентов
m_pView->bkgndColor = m_pController->bkcolor;
m_pModel->ChangeSpeed(m_pController->speed);
Из этой части кода видно, что интерфейс классов оболочек позволяет использовать свойства как члены-переменные соответствующих классов, получая либо изменяя значения свойств.
Это все, что потребуется изменить в функции OnInitialUpdate(), за одним исключением. Весьма полезно заключить приведенные выше строки в блок try: catch, поскольку классы-оболочки с интеллектуальными указателями возвращают результат вызовов методов интерфейсов через параметр HRESULT. Если его значение указывает на ошибку, класс-оболочка порождает исключение типа _com_error. В случае возникновения ошибки ее лучше обработать внутри блока обработки исключений. Для этого нужно разрешить обработку исключений для проекта. В проектах MFC она разрешена по умолчанию, а вот в проектах ATL - нет.