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



         

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


STDMETHODIMP_(ULONG) Surfboard::XCPShutdownNotify::Release(void) { return This()->Release(); /* Release containing object */ /* Release объекта-контейнера */ }

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

Клиенты находят интерфейсы объекта IConnectionPoint посредством вызова метода объекта FindConnectionPoint, который для класса Surfboard мог бы выглядеть примерно так:

STDMETHODIMP Surfboard::FindConnectionPoint(REFIID riid, IConnectionPoint **ppcp) { if (riid == IID_IShutdownNotify) *ppcp = IID_IShutdownNotify; else if (riid == IID_ISurfboardUser) *ppcp = &m_xcpSurfboardUser; else return (*ppcp = 0), CONNECT_E_NOCONNECTION; (*ppcp)->AddRef(); return S_OK; }

Отметим, что объект выдает интерфейсные указатели IConnectionPoint только при запросе тех интерфейсов, на которые он сможет сделать обратный запрос. Необходимо указать также на поразительное сходство с большинством реализации QueryInterface. Основное различие состоит в том, что QueryInterface имеет дело с импортируемыми (inbound) интерфейсами, в то время как FindConnectionPoint — с экспортируемыми (outbound) интерфейсами.

Поскольку метод IConnectionPoint::Advise принимает только интерфейс IUnknown, статически типизированный как интерфейсный указатель обратного вызова, то реализации Advise должны использовать QueryInterface для того, чтобы привязать указатель обратного вызова к соответствующему типу интерфейса:

STDMETHODIMP Surfboard::XCPShutdownNotify::Advise(IUnknown *pUnk, DWORD *pdwCookie) { assert (pdwCookie && pUnk); *pdwCookie = 0; if (This()->m_pShutdownNotify) // already have one // уже имеем один return CONNECT_E_ADVISELIMIT; // QueryInterface for correct callback type // QueryInterface для корректирования типа обратного вызова HRESULT hr = pUnk->QueryInterface(IID_IShutdownNotify, (void**)&(This()->m_pShutdownNotify)); if (hr == E_NOINTERFACE) hr = CONNECT_E_NOCONNECTION; if (SUCCEEDED(hr)) // make up a meaningful cookie // готовим значимый маркер *pdwCookie = DWORD(This()->m_pShutdownNotify); return hr; }




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