Сущность технологии COM



         

Двунаправленные интерфейсные контракты - часть 2


При таком парном определении интерфейса должен существовать некий механизм для информирования объекта-программиста о том, что у клиента имеется реализация ISoftwareConsumer, с помощью которой он может получать уведомления от объекта-программиста об изменениях состояния. Одной из распространенных методик является определение IProgrammer таким образом, чтобы он имел явные методы, через которые клиенты могли бы связываться со своими объектами-потребителями (consumer object). Канонической формой этой идиомы является включение метода Advise:

interface IProgrammer : IUnknown { HRESULT Advise ([in] ISoftwareConsumer *psc, [out] DWORD *pdwCookie); : : :

посредством которого клиент подготавливает парный объект-потребитель, а программист возвращает DWORD для подтверждения связи. Затем этот DWORD можно было бы использовать в соответствующем методе Unadvise:

interface IProgrammer : IUnknown { : : : HRESULT Unadvise([in] DWORD dwCookie); }

для того, чтобы сообщить объекту-программисту о прерывании связи. При использовании уникальных DWORD для представления связи программист-потребитель дизайн интерфейса позволяет произвольному числу потребителей независимо друг от друга соединяться с объектом и отсоединяться от него.

Если эти два метода имеются в интерфейсе IProgrammer, то реализация программиста может быть соединена с объектом-потребителем с помощью метода Advise

STDMETHODIMP Programmer::Advise(ISoftwareConsumer *pcs, DWORD *pdwCookie) { assert(pcs); if (m_pConsumer != 0) // is there already a consumer? // уже есть потребитель? return E_UNEXPECTED; (m_pConsumer = pcs)->AddRef(); // hold onto new consumer // соединяемся с новым потребителем *pdwCookie = DWORD(pcs); // make up a reasonable cookie // готовим подходящий маркер return S_OK; }

Соответствующая реализация метода Unadvise выглядела бы примерно так:

STDMETHODIMP Programmer::Unadvise(DWORD dwCookie) { // does the cookie correspond to the current consumer? // соответствует ли маркер данному потребителю? if (DWORD(m_pConsumer) != dwCookie) return E_UNEXPECTED; (m_pConsumer)->Release(); // release current consumer // освобождаем текущего потребителя m_pConsumer = 0; return S_OK; }




Содержание  Назад  Вперед