Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Роджерсон Д. - Основы COM - 2000.pdf
Скачиваний:
406
Добавлен:
13.08.2013
Размер:
2.4 Mб
Скачать

72

{

virtual void __stdcall Fx() = 0; };

interface IY : IUnknown

{

virtual void __stdcall Fy() = 0; };

interface IZ : IUnknown

{

virtual void __stdcall Fz() = 0; };

// Предварительные объявления GUIDs extern "C"

{

extern const IID IID_IX; extern const IID IID_IY; extern const IID IID_IZ;

}

Листинг 5-5 Объявления интерфейсов

Как видите, клиент и компонент по-прежнему используют интерфейсы IX, IY и IZ. Идентификаторы этих интерфейсов объявлены в конце IFACE.H. IID будут обсуждаться в следующей главе. Определения идентификаторов интерфейсов находятся в файле GUIDS.CPP, который показан в листинге 5-6.

GUIDS.CPP

//

// GUIDs.cpp – Идентификаторы интерфейсов

//

#include <objbase.h>

extern "C"

{

// {32bb8320-b41b-11cf-a6bb-0080c7b2d682} extern const IID IID_IX =

{0x32bb8320, 0xb41b, 0x11cf,

{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// {32bb8321-b41b-11cf-a6bb-0080c7b2d682} extern const IID IID_IY =

{0x32bb8321, 0xb41b, 0x11cf,

{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// {32bb8322-b41b-11cf-a6bb-0080c7b2d682} extern const IID IID_IZ =

{0x32bb8322, 0xb41b, 0x11cf,

{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// extern необходим, чтобы для констант C++ была выделена память

}

Листинг 5-6 Идентификаторы интерфейсов определены в GUIDS.CPP. С этим файлом компонуются и клиент, и компонент.

Это были детали реализации компонента в DLL. Давайте немного поиграем с такими компонентами.

Связки объектов

Теперь Вы можете поиграть с компонентами и посмотреть, как они динамически компонуются. В каталоге CHAP05 содержится код трех клиентов; это Клиент 1, Клиент 2 и Клиент 3. Здесь же находится код трех компонентов, которые мы обозначим как Компонент 1, Компонент 2 и Компонент 3. Код в IFACE.H определяет три интерфейса: IX, IY и IZ. Клиент 1 и Компонент 1 поддерживают интерфейс IX. Клиент 2 и Компонент 2 поддерживают интерфейсы IX и IY. Клиент 3 и Компонент 3 поддерживают все три интерфейса. В табл. 5-1 показан набор интерфейсов, поддерживаемых каждым клиентом и компонентом.

73

Таблица 5-1 Эта таблица показывает, какие интерфейсы поддерживаются каждым клиентом и компонентом

 

IX

IY

IZ

 

Клиент 1

#

 

 

Компонент 1

Клиент 2

#

#

 

Компонент 2

Клиент 3

#

#

#

Компонент 3

Все клиенты и компоненты компилируются по команде

nmake –f makefile

Каждый из клиентов при запуске спрашивает, какой компонент он должен использовать. Введите имя компонента и нажмите <Enter>. Клиент с соответствующим партнером. Затем он запросит у компонента каждый известный ему интерфейс. Если компонент поддерживает интерфейс, клиент вызовет функцию этого интерфейса. В противном случае клиент сломается.

Я хотел просто посмотреть, не заснули ли Вы. Клиент не сломается, а компонент напечатает симпатичное маленькое сообщение о том, что не поддерживает интерфейс. Ниже приведен пример работы Клиента 2 и Компонентом 2 и Клиента 3 с Компонентом 1.

C:\client2

Введите имя файла компонента [Cmpnt?.dll]: cmpnt2.dll

Клиент 2: Получить указатель на IUnknown Компонент 2: Возвратить указатель на IUnknown Клиент 2: Получить интерфейс IX

Компонент 2: Возвратить указатель на IX Клиент 2: IX получен успешно

Fx

Клиент 2: Получить интерфейс IY Компонент 2: Возвратить указатель на IY Клиент 2: IY получен успешно

Fy

Клиент 2: Освободить интерфейс IUnknown Компонент 2: Ликвидировать себя

C:\client3

Введите имя файла компонента [Cmpnt?.dll]: cmpnt1.dll

Клиент 3: Получить указатель на IUnknown Клиент 3: Получить интерфейс IX Компонент 1: Возвратить указатель на IX Клиент 3: IX получен успешно

Fx

Клиент 3: Получить интерфейс IY Компонент 1: Интерфейс не поддерживается Клиент 3: Не могу получить интерфейс IY Клиент 3: Получить интерфейс IZ Компонент 1: Интерфейс не поддерживается Клиент 3: Не могу получить интерфейс IZ Клиент 3: Освободить интерфейс IUnknown Компонент 1: Ликвидировать себя

Компонент 2 реализует все интерфейсы, нужные клиенту 2. Компонент 1 реализует только IX, тогда как Компоненту 3 нужны все три интерфейса: IX, IY и IZ. Попробуйте другие комбинации компонентов и клиентов.

Вам понравилось? По-моему, это замечательно. Мы успешно создали архитектуру, которая позволяет подключать друг к другу компоненты и клиенты во время выполнения. Подозреваю, что Вы хотите пойти это отметить, так что я закругляюсь.

Негибкое связывание, резюме

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

74

Как бы ни были гибки наши компоненты, по-прежнему остается один момент, в котором гибкости не хватает, — момент создания. CallCreateInstance требует, чтобы клиент знал имя DLL, в которой реализован компонент. Имя DLL — это деталь реализации, которую нам хотелось бы скрыть от клиента. Компонент должен быть способен изменить имя DLL, в которую он погружен, и не повлиять на клиентов. Хотелось бы также поддерживать в одной DLL несколько компонентов. Эти вопросам и посвящены следующие две главы.

Соседние файлы в предмете Программирование на C++