《5.第五讲 可连接对象&结构化存储》由会员分享,可在线阅读,更多相关《5.第五讲 可连接对象&结构化存储(58页珍藏版)》请在金锄头文库上搜索。
1、1,COM:可连接对象 & 结构化存储,2,内容,复习:COM基础可连接对象结构化存储,3,聚合模型的关键,复习:COM基础,4,可连接对象(connectable object),内容:可连接对象结构模型实现可连接对象(源对象)客户-源对象-接收器的协作过程可连接对象的程序实现,5,双向通信机制 客户与可连接对象的关系,6,两个概念,入接口(incoming interface)组件对象实现入接口,客户通过入接口调用对象提供的功能客户和组件都需要知道接口的类型信息出接口(outgoing interface)客户端提供的COM对象实现出接口组件端的对象通过出接口调用客户提供的功能组件提供接口
2、类型信息,客户实现该接口类似于回调(callback),但是要复杂和灵活得多,7,出接口,类型信息由组件一方提供客户提供出接口的实现,实现出接口的COM对象被称为接收器对象(sink)sink没有CLSID,也不需要类厂也是一个COM接口,有IID每个成员函数代表了:事件event通知notification请求request,8,源对象 or 可连接对象,Connectable object,source普通的COM对象,支持一个或者多个出接口提供出接口的类型信息通过IProvideClassInfo2接口通过typelib,9,客户与可连接对象之间的两种结构,10,可连接对象的基本结构,1
3、1,可连接对象,如何管理多个出接口每个出接口对应一个连接点对象通过连接点枚举器管理对于每个出接口,如何管理多个客户连接通过连接枚举器管理多个连接,12,实现可连接对象(源对象)(一),枚举器内部对象,不需要类厂和CLSID其含义就如同指针智能指针枚举器接口模板class IEnum : public IUnknownvirtual HRESULT Next( ULONG celt, ELT_T *rgelt, ULONG *pceltFetched ) = 0;virtual HRESULT Skip( ULONG celt ) = 0;virtual HRESULT Reset( void
4、) = 0;virtual HRESULT Clone( IEnum*ppenum ) = 0;,13,枚举器的用法,class IStringManager : public IUnknown virtual IEnumString* EnumStrings(void) = 0;void SomeFunc(IStringManager * pStringMan) String psz; IEnumString * penum; penum=pStringMan-EnumStrings(); while (S_OK = penum-Next(1, ,14,实现可连接对象(源对象)(二),ICo
5、nnectionPointContainer接口class IConnectionPointContainer : public IUnknown virtual HRESULT EnumConnectionPoints(IEnumConnectionPoints *) = 0; virtual HRESULT FindConnectionPoint(const IID *, IConnectionPoint *) = 0;IEnumConnectionPoints接口class IEnumConnectionPoints : public IUnknownvirtual HRESULT Ne
6、xt( ULONG cConnections, IConnectionPoint *rgpcn, ULONG *pcFetched) = 0; virtual HRESULT Skip( ULONG cConnections) = 0;virtual HRESULT Reset(void) = 0;virtual HRESULT Clone( IEnumConnectionPoints *ppEnum) = 0;,15,实现可连接对象(源对象)(三),连接点和IConnectionPoint接口class IConnectionPoint : public IUnknown virtual H
7、RESULT GetConnectionInterface( IID *pIID) = 0; virtual HRESULT GetConnectionPointContainer( IConnectionPointContainer *ppCPC) = 0; virtual HRESULT Advise( IUnknown *pUnk, DWORD *pdwCookie) = 0; virtual HRESULT Unadvise( DWORD dwCookie) = 0; virtual HRESULT EnumConnections(IEnumConnections*ppEnum) =
8、0; ;连接枚举器 实现IEnumConnections接口允许多个客户连接每个连接用struct CONNECTDATA来描述,16,回顾:可连接对象的基本结构,17,客户与源对象建立连接过程,客户请求IConnectionPointContainer接口客户调用IConnectionPointContainer:FindConnectionPoint找到连接点对象客户调用IConnectionPoint:Advise建立与接收器的连接最后,客户调用IConnectionPoint:Unadvise取消连接,并释放连接点对象,18,客户方基本结构,客户方实现接收器对象(sink)支持多个与可
9、连接对象之间的连接一般只实现专用的出接口(IUnknown除外)不需要类厂、CLSID与客户代码紧密连接起来建立连接1 通过IConnectionPointContainer接口找到连接点对象2 通过连接点对象建立连接连接点相当于连接管理器,19,接收器的实现,class CSomeEventSet : public ISomeEventSet private: ULONG m_cRef; / Reference count . / other private data members public: DWORD m_dwCookie; / Connection key public: CSo
10、meEventSet (); CSomeEventSet(void); /IUnknown members STDMETHODIMP QueryInterface(REFIID, PPVOID); STDMETHODIMP_(DWORD) AddRef(void); STDMETHODIMP_(DWORD) Release(void); STDMETHODIMP SomeEventFunction ( . ); .;,20,接收器的用法,ISomeEventSet *gpSomeEventSet;./ InitializeCSomeEventSet *pSink = new CSomeEven
11、tSet;pSink-QueryInterface(IID_ISomeEventSet, pSomeEventSet ); / Reference count is 1./ connections the sink object to the connectable object we havehr=pConnectionPoint-Advise(pSomeEventSet , / Reference count is 0,21,事件的激发和处理,BOOL CSourceObject:FireSomeEvent(IConnctionPoint *pConnectionPoint) IEnumC
12、onnections *pEnum; CONNECTDATA connectionData; if (FAILED(pConnectionPoint-EnumConnections(,22,与出接口有关的类型信息,客户如何知道出接口?运行时刻?编译时刻?动态构造接收器对象?动态构造vtable?支持部分成员?类型信息的协商通过IProvideClassInfo2能否用标准的接口作为出接口?,23,用IDispatch接口作为出接口(一),IDispatch接口class IDispatch : public IUnknown public: virtual HRESULT GetTypeInf
13、oCount( UINT *pctinfo) = 0; virtual HRESULT GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo *ppTInfo) = 0; virtual HRESULT GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) = 0; virtual HRESULT Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, D
14、ISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) = 0;,24,用IDispatch接口作为出接口(二),25,IDispatch出接口的事件激发函数,void CMySourceObj:FireMyMethod (short nInt)COleDispatchDriver driver;POSITION pos = m_xMyEventSet.GetStartPosition();LPDISPATCH pDispatch;while (pos != NULL) pDispatch = (LPDISPATCH) m_xMyEventSet.GetNextConnection(pos);ASSERT(pDispatch != NULL);driver.AttachDispatch(pDispatch, FALSE);TRYdriver.InvokeHelper(eventidMyMethod, DISPATCH_METHOD, VT_EMPTY, NULL,(BYTE *) (VTS_I2), nInt);END_TRYdriver.DetachDispatch();,26,用连接点机制实现回调的讨论,