IConnectionPointContainer *pcpc = 0;

HRESULT hr = pUnkObject->QueryInterface(IID_IConnectionPointContainer, (void**) &pcpc);

if (SUCCEEDED(hr)) {

IConnectionPoint *pcp = 0;

hr =pcpc->FindConnectionPoint(IID_IShutdownNotify,&pcp);

if (SUCCEEDED(hr)) {

hr = pcp->Unadvise(dwCookie);

pcp->Release();

}

pcpc->Release();

}

}

Отметим, что в обоих примерах клиент использует метод IConnectionPointContainer::FindConnectionPoint для вызова из объекта его IShutdownNotify-реализации IConnectionPoint. Если объект отклоняет вызов FindConnectionPoint, это говорит о том, что он не понимает семантику интерфейса IShutdownNotify. Это оберегает пользователя от прикрепления произвольных интерфейсов обратного вызова к объекту без полного согласия на это разработчика объекта.

Как и в случае с IUnknown, реализации IConnectionPointContainer и IConnectionPoint в значительной степени типичны. Объекту C++ требуется отдельная единица идентификации СОМ для каждого типа экспортируемого интерфейса, который он предполагает поддерживать. Одна из методик реализации ConnectionPoint состоит в использовании того варианта методики вложения класса/композиции, которая учитывает различия в отношениях тождественности:

class Surfboard : public ISurfboard,

public IHazardousDevice,

public ISharkBait,

public IConnectionPointContainer {

LONG m_cRef; // СОM reference count

// счетчик ссылок СОМ

// Surfboards don't support multiple outbound interfaces

// of a given type, so it simply declares single pointers

// of each possible type of callback interface

// Surfboard не поддерживает несколько экспортируемых

// интерфейсов заданного типа, поэтому он просто

// объявляет одиночные указатели каждого возможного

// типа интерфейса обратного вызова

IShutdownNotify *m_pShutdownNotify;

ISurfboardUser *m_pSurfer;

// to deal with identity relationship of IConnectionPoint,

// define an IShutdownNotify-specific nested class + member

// для работы с отношением тождественности

// IConnectionPoint, определяем специфический для

// IShutdownNotify вложенный класс+член

class XCPShutdownNotify : public IConnectionPoint {

Surfboard *This(void);

// use fixed offset

// испопьзуем постоянное смещение

// IUnknown methods...

// методы IUnknown...

// IConnectionPoint methods...

// методы IConnectionPoint...

} m_xcpShutdownNotify;

// define an ISurfboardUser-specific nested class + member

// определяем специфический для IShutdownNotify вложенный класс+член

class XCPSurfboardUser : public IConnectionPoint {

Surfboard *This(void);

// use fixed offset

// используем постоянное смещение

// IUnknown methods...

// методы IUnknown...

// IConnectionPoint methods...

// методы IConnectionPoint...

} m_xcpSurfboardUser;

// IUnknown methods...

// методы IUnknown...

// ISurfboard methods...

// методы ISurfboard...

// IHazardousDevice methods...

// методы IHazardousDevice...

// ISharkBait methods...

// методы ISharkBait...

// IConnectionPointContainer methods...

// методы IConnectionPointContainer...

};

Следует указать, что экземпляры класса Surfboard будут иметь две отдельные реализации IConnectionPoint, одна из которых используется для присоединения интерфейсов обратного вызова IShutdownNotify, а вторая – для присоединения интерфейсов ISurfboardUser. Эти две реализации разделены на отдельные классы C++, что позволяет каждой реализации IConnectionPoint иметь свои собственные уникальные реализации IUnknown и IConnectionPoint. В частности, может иметься три отдельных реализации QueryInterface со своими собственными наборами интерфейсных указателей, которые могут быть выделены для создания трех отдельных СОМ-копий.

Из приведенного выше определения класса следует такая QueryInterface-peaлизация основного класса Surfboard:

STDMETHODIMP Surfboard::QueryInterface(REFIID riid, void**ppv)

{

if (riid == IID_IUnknown || riid == IID_ISurfboard)

*ppv = static_cast<ISurfboard*>(this);

else if (riid == IID_IHazardousDevice)

*ppv = static_cast< IHazardousDevice *>(this);

else if (riid == IID_ISharkBait)

*ppv = static_cast<ISharkBait *>(this);

else if (riid == IID_IConnectionPointContainer)

*ppv = static_cast<IConnectionPointContainer *>(this);

else

return (*ppv = 0), E_NOINTERFACE;

((IUnknown*)*ppv)->AddRef();

return S_OK;

}

Отметим, что доступ к интерфейсу IConnectionPoint не может быть осуществлен через эту главную

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату