无论是对象聚合或是对象包容,其作用都是组件的复用,使用环境是这样的,有组件some对象和other对象,我们暴露出来的是some对象,现在需求改变了,some要加入新
的功能,而该功能已经被other组件对象实现,而且完全不需要修改,在这种情况下,使用对象聚合,即,首先获得Isome的接口,使用其功能,在Isome接口中使用
QueryInterface函数,获得Iother接口,进而复用其功能。现在说下,在WIN7+VS2010的编程环境下:
外部对象声明:
class ATL_NO_VTABLE Csome : public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<Csome,&CLSID_some>,public IDispatchImpl<Isome,&IID_Isome,&LIBID_neoLib,/*wMajor =*/ 1,/*wMinor =*/ 0> { public: Csome() { } DECLARE_REGISTRY_RESOURCEID(IDR_SOME) DECLARE_GET_CONTROLLING_UNKNOWN() //这点是自己添加的,至于其含义,请自行百度... BEGIN_COM_MAP(Csome) COM_INTERFACE_ENTRY(Isome) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pInner.p) //聚合B组件的IB接口,也可以使用COM_INTERFACE_ENTRY_AUTOAGGREGATE宏,则不需要在FinalConstruct //函数中创建B对象。 END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { HRESULT hr = S_OK; if(!m_pInner) //此处主要用于创建内部对象,并传递进去Isome的指针 hr = ::CoCreateInstance(CLSID_other,GetControllingUnknown(),CLSCTX_INPROC_SERVER,IID_IUnknown,(void**)&m_pInner); return hr; } void FinalRelease() { m_pInner.Release(); } public: CComPtr<IUnknown>m_pInner;//这儿使用智能指针 STDMETHOD (someMsg)(BSTR var)//该函数用于测试 { MessageBox(NULL,var,L"SOME",0); return S_OK; } }; OBJECT_ENTRY_AUTO(__uuidof(some),Csome)
内部对象的实现:
class ATL_NO_VTABLE Cother : public CComObjectRootEx,public CComCoClass,public IDispatchImpl { public: Cother() { } DECLARE_REGISTRY_RESOURCEID(IDR_OTHER) DECLARE_AGGREGATABLE(Cother); //声明组件Cother可以被聚合,这也是自己添加的 BEGIN_COM_MAP(Cother) COM_INTERFACE_ENTRY(Iother) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: STDMETHOD(otherMsg)(BSTR var) { MessageBox(NULL,L"other",0); return S_OK; } }; OBJECT_ENTRY_AUTO(__uuidof(other),Cother)
测试文件:
#include "stdafx.h" #include #include using namespace std; #import"D:\project\neo\Debug\neo.dll" no_namespace #include"D:\project\neo\neo\neo_i.c" int _tmain(int argc,_TCHAR* argv[]) { ::CoInitialize(NULL); IsomePtr somePtr; HRESULT hr=somePtr.CreateInstance(__uuidof(some)); Isome* psome=NULL; hr=somePtr.QueryInterface(IID_Isome,(void**)&psome); if(S_OK!=hr) { return 0; } psome->someMsg(L"some have a try"); Iother* pother=NULL; hr=psome->QueryInterface(IID_Iother,(void**)&pother); if(S_OK!=hr) { return 0; } pother->otherMsg(L"other have a try"); pother->QueryInterface(IID_Isome,(void**)&psome); psome->someMsg(L"DSHAIDA"); somePtr.Release(); ::CoUninitialize (); return 0; }
笔者在进行测试过程中遇到了两个问题,很是诡异,
1.是在CreateInstance中返回没有注册类,可是本来不用regsvr32的,但是,regsvr32注册过后也不行,
解决方案是: 最后发现是在FinalStruct函数出现了错误。
2.是IID_Isome中出现了连接错误无法解析的外部符号IID_(这里是开发者自己写的接口名称),
解决方案是:
不再使用#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,{b1,b8}}
MIDL_DEFINE_GUID(IID,IID_Isome,0xDB21B3C7,0xF4EC,0x4152,0x9B,0xFB,0xE5,0xC3,0xB8,0x4D,0x91);
而是加入了#include"D:\project\neo\neo\neo_i.c"定义文件,最后测试成功!一天啊同学们....