>>從MSDN翻譯
___________________
當一個偵測到某些事情發生后,它能夠通知她的客戶端。例如,一個“證券行情自動記錄收報機”程序發現一種證券價格發生了變化,它能夠把這個變化通知給所有的客戶端。這個通知進程是通過事件來觸發的。
對于COM,服務對象可以使用COM事件來觸發不帶任何通知信息的事件。對象也可以使用可連接對象,在客戶上實現輸出接口,對象使用這些出接口來與客戶進行通信。COM可連接對象的輸出接口是由客戶程序來實現,客戶利用一種被稱為接收器(sink)的對象來實現這些接口,并把接口指針告訴對象。因此對象可以通過這和客戶保證定向的通信了(相當于建了一個專用通道,來保證對象與客戶之間的通信)。輸入接口在對象上實現,接受來自
對象的外部客戶的調用;輸出接口在客戶的接收器(sink)上實現接受來自對象的調用。對象定義他要使用的接口,客戶來實現他。
對象提供他的入接口,并且實現他們??蛻敉ㄟ^對象IUnknown::QueryInterface方法來獲得對象的入接口,如果對象支持客戶請求的操作,則執行。 輸出接口也在對象上定義,但是他確是在客戶上創建的接收器對象上實現。對象接收器對象輸出接口上的方法,通知客戶對象上所作的改變,觸發客戶上的事件。
可連接對象為對象到客戶的通信提供了一個通用的機制。任何愿意暴露事件或者任何種類的通知都可以使用這一技術。另外,COM還提供了很多專用的接收器用于通知客戶感興趣的指定的事件。例如 接口 可以用于通知客戶對象的數據和視圖的變化。
可連接對象僅僅是可連接對象結構的一部分,這項技術包括了以下幾個元素:
下圖表示了客戶、可連接對象、接收器對象、連接點對象之間的關系:
在上圖第3步,連接點對象調用接收器接口的方法之前,它必須通過QueryInterface()來得到指定的接口?;蛘呓涌诘闹羔樤诘?步時已通過Advise()方法獲得。
兩個枚舉對象也包含在這個結構之中,盡管他沒有在事例中體現出來。一個是通過IConnectionPointContainer 接口的方法創建,用來枚舉可連接對象的連接點。另一個通過IConnectionPoint接口的方法創建,用來枚舉指定的連接點的當前已建立連接。一個連接點能夠支持多個連接接收器接口,每次在此接口上調用一個方法時,他通過迭代一個裝有所有連接點的列表來獲取指定的連接接收器接口的指針。這個過程就叫做列集。
當使用可連接對象時,弄清楚 可連接對象、每個連接點、每個接收器 和all enumerators are separate objects with separate IUnknown implementations, separate reference counts, and separate lifetimes. 客戶使用這些對象后總是有責任釋放他自己的引用計數。
注意:一個可連接對象可以支持多個客戶,也能夠支持來自一個客戶的多個接收器。
同樣,一個接收器也能夠來接多個可連接對象。
在客戶與可連接對象之間依照下列步驟建立一個連接:
1. 客戶通過查詢對象的IConnectionPointContainer 決定對象是否是可連接
的。如果 返回成功,客戶用一個指針指向可連接對象的
IConnectionPointContainer 接口。
使可連接對象的引用計數增加。如果對象是不可連接的,它就不支持輸出接口。
2. 如果對象是可連接的,客戶就試著獲取可連接對象的一個可連接點的
IConnectionPoint 接口的指針。有兩種方法來獲取這個指針,他們是
和
. 如果使用后者,還要
先進行一些其他步驟。(請參見 來獲取更多
信息)。
如果調用成功,那么可連接對象和客戶都支持相同的輸出接口??蛇B接對象定義他
調用他,客戶實現他。接著客戶就能夠通過可連接對象的內的連接點進行通信了。
3. 客戶調用 方法來建立接收器和可連接對象的連接點
之間的連接。調用了這個方法后,對象的連接點獲得了接收器的輸出指針。
4. IConnectionPoint::Advise 中的代碼調用 已經通過的接口指針的
QueryInterface 方法,來請求他連接方得指定的接口。
The code inside IConnectionPoint::Advise calls QueryInterface
on the interface pointer that is passed in, asking for the specific
interface identifier to which it connects.
5. 對象通過他連接點上所持有的指針,從需要的接收器接口上調用方法。
6. 客戶調用 終止此次連接??蛻粼僬{用IConnectionPoint::Release 釋放連接的指針。連接對象也需要釋放相應的指針,所以客戶必須調用 IConnectionPointContainer::Release 來釋放可連接對象所擁有的相應的指針。
支持可連接對象要求支持以下4個接口:
后兩個是為The IConnectionPoint * 定義的標準的枚舉類型.(有關枚舉的更多信息請參見 )另外,可連接對象可隨意支持 和 為客戶輸出接口的運行時支持提供了足夠的信息。最終客戶必須提供一個接收器輸出接口的實現,該接口在可連接對象上被定義。
IConnectionPointContainer, IConnectionPoint, IProvideClassInfo, and IProvideClassInfo2 接口的定義事例:
interface IConnectionPointContainer : IUnknown
{
HRESULT EnumConnectionPoints([out] IEnumConnectionPoints
**ppEnum);
HRESULT FindConnectionPoint([in] REFIID riid ,
[out] IConnectionPoint **ppCP);
}
interface IConnectionPoint : IUnknown
{
HRESULT GetConnectionInterface([out] IID *pIID);
HRESULT GetConnectionPointContainer([out]
IConnectionPointContainer **ppCPC);
HRESULT Advise([in] IUnknown *pUnk, [out] DWORD *pdwCookie);
HRESULT Unadvise([in] DWORD dwCookie);
HRESULT EnumConnections([out] IEnumConnections **ppEnum);
}
interface IProvideClassInfo : IUnknown
{
HRESULT GetClassInfo([out] ITypeInfo **ppTI);
}
interface IProvideClassInfo2 : IProvideClassInfo
{
HRESULT GetGUID( );
}
原文轉自:http://www.anti-gravitydesign.com