COM学习笔记(十一 ):聚合的一个完整例子
//Cmpnt1.cpp -- Component1 #include <iostream.h> #include <objbase.h> #include "Iface.h" #include "Registry.h" void trace(const char* msg){cout<<"Component1; t "<<msg<<endl;} static HMODULE g_hModule = NULL; static long g_cComponents = 0; static long g_cServerLocks = 0; const char g_szFriendlyName[] = "Inside COM,Component1"; const char g_szProgID[] = "InsideCOM.Cmpnt1_1"; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class CA : public IX{ public: virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); virtual void __stdcall Fx(){cout<<"Fx"<<endl;} virtual void __stdcall Fy(){m_pIY->Fy();} CA(); ~CA(); HRESULT __stdcall Init(); private: long m_cRef; IY* m_pIY; IUnknown* m_pUnknownInner; }; CA::CA():m_cRef(1),m_pUnknownInner(NULL){ InterlockedIncrement(&m_cComponents); } CA::~CA(){ InterlockedDecrement(&g_cComponents); trace("Destroy self."); m_cRef = 1; IUnknown* pUnknownOuter = this; pUnknownOuter->AddRef(); m_pIY->Release(); if(m_pUnknownInner != NULL){ m_pUnknownInner->Release(); } HRESULT __stdcall CA::Init(){ IUnknown* pUnknownOuter = this; trace("Create inner component."); HRESULT hr = ::CoCreateInstance(CLSID_Component2,pUnknownOuter,CLSCTX_INPROC_SERVER,IID_IUnknown,(void**)&m_pUnknownInner); if(FAILED(hr)){ trace("Could not create contained component."); return E_FAIL; } hr = m_pUnknownInner->QueryInterface(IID_IY,(void**)&m_pIY); if(FAILED(hr)){ trace("Inner component does not support interface IY."); m_pUnknowInner->Release(); return E_FAIL; } pUnknownOuter->Release(); return S_OK; } HRESULT __stdcall CA::QueryInterface(const IID& iid,void** ppv){ if(iid == IID_IUnknown){ *ppv = static_cast<IUnknown*>(this); } else if(iid == IID_IX){ *ppv = static_cast<IX*>(this); } else if(iid == IID_IY){ trace("Return inner component's IY interface."); return m_pUnknownInner->QueryInterface(iid,ppv); //or *ppv = m_pIY; } else{ *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; } ULONG __stdcall CA::AddRef(){ return InnerlockedIncrement(&m_cRef); } ULONG __stdcall CA::Release(){ id(InterlockedDecrement(&m_cRef) == 0){ delete this; return 0; } return m_cRef; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class CFactory : public IClassFactory{ public: virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,const IID& iid,void** ppv); virtual HRESULT __stdcall Lockserver(BOOL bLock); CFactory() : m_cRef(1){} ~CFactory(){} private: long m_cRef; }; HRESULT __stdcall CFactory::QueryInterface(const IID& iid,void** ppv){ IUnknown* pI; if((iid == IID_IUnknown) || (iid == IID_IClassFactory)){ pI = static_cast<IClassFactory*>(this); } else{ *ppv = NULL; return E_NOINTERFACE; } pI->AddRef(); *ppv = pI; return S_OK; } ULONG CFactory::AddRef(){ return InterlockedIncrement(&m_cRef); } ULONG CFactory::Release(){ if(InterlockedDecrement(&m_cRef) == 0){ delete this; return 0; } return m_cRef; } HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,void** ppv){ HRESULT hr = E_FAIL; if(pUnknownOuter != NULL){ return CLASS_E_NOAGGREGATION; } CA* pA = new CA; if(pA == NULL){ return E_OUTOFMEMORY; } hr = pA->Init(); //创建组件2,并请求IY接口 if(FAILED(hr)){ pA->Release(); return hr; } hr = pA->QueryInterface(iid,ppv); pA->Release(); return hr; } HRESULT __stdcall CFactory::LockServer(BOOL bLock){ if(bLock){ InterlockedIncrement(&g_cServerLocks); } else{ InterlockedDecrement(&g_cServerLocks); } return S_OK; } STDAPI DllCanUnloadNow(){ if((g_cComponents == 0) && (g_cServerLocks == 0)){ return S_OK; } else{ return S_FALSE; } } //Get class factory STDAPI DllGetClassObject(const CLSID& clsid,void** ppv){ if(clsid != CLSID_Component1){ return CLASS_E_CLASSNOTAVAILABLE; } CFactory* pFactory = new CFactory; if(pFactory == NULL){ return E_OUTOFMEMORY; } HRESULT hr = pFactory->QueryInterface(iid,ppv); pFactory->Release(); return hr; } STDAPI DllRegisterServer(){ return RegisterServer(g_hModule,CLSID_Component1,g_szFriendlyName,g_szVerIndProgID,g_szProgID); } STDAPI DllUnregisterServer(){ return UnregisterServer(CLSID_Component1,g_szProgID); } BOOL APIENTRY DllMain(HANDLE hModule,DWORD dwReason,void* lpReserved){ if(dwReason == DLL_PROCESS_ATTACH){ g_hModule = hModule; } return TRUE; } //**************************************************************************************************************************************** //Cmpnt2.cpp -- Component2 #include <iostream.h> #include <objbase.h> #include "Iface.h" #include "Registry.h" void trace(const char* msg){cout<<"Component2: t"<<msg<<endl;} static HMODULE g_hModule = NULL; static long g_cComponents = 0; static long g_cServerLocks = 0; const char g_szFriendlyName[]="Inside COM.Component2"; const char g_szVerIndProgID[] = "InsideCOM.Cmpnt2"; const char g_szProgID[] = "InsideCOM.Cmpnt2._1"; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class CB : public IY,public INondelegatingUnknown{ public: virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv){ trace("Delegate QueryInterface."); return m_pUnknownOuter->QueryInterface(iid,ppv); } virtual ULONG __stdcall AddRef(){ trace("Delegate AddRef."); return m_pUnknownOuter->AddRef(); } virtual ULONG __stdcall Release() { trace("Delegate Release"); return m_pUnknownOuter->Release(); } virtual HRESULT __stdcall NondelegatingQueryInterface(const IID& iid,void** ppv); virtual ULONG __stdcall NondelegatingAddRef(); virtual ULONG __stdcall NondelegatingRelease(); virtual void __stdcall Fy(){cout<<"Fy"<<endl;} CB(IUnknown* m_pUnknownOuter); ~CB(); private: long m_cRef; IUnknown* m_pUnknownOuter; }; HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid,void** ppv){ if(iid == IID_IUnknown){ *ppv = static_cast<INondelegatingUnknown*>(this); //very important !!! } else if(iid == IID_IY){ *ppv = static_cast<IY*>(this); } else{ *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; } ULONG __stdcall CB::NondelegatingAddRef(){ return InterlockedIncrement(&m_cRef); } ULONG __stdcall CB::NondelegatingRelease(){ if(InterlockedDecrement(&m_cRef = 0)){ delete this; return 0; } return m_cRef; } CB::CB(IUnknown* pUnknownOuter) : m_cRef(1){ ::InterlockedIncrement(&g_cComponents); if(pUnknownOuter == NULL){ trace("不是代理未知接口;让我们委托给非代理未知接口吧"); m_pUnknownOuter = reinterpret_cast<IUnknown*>(static_cast<INondelegatingUnknown*>(this)); } else{ trace("Aggregating; delegate to outer IUnknown."); m_pUnknownOuter = pUnknownOuter; } } CB::~CB(){ InterlockedDecrement(&g_cComponents); trace("Destroy self"); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class CFactory : public IClassFactory{ public: virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv ); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,void** ppv); virtual HRESULT __stdcall LockServer(BOOL bLock); CFactory() : m_cRef(1){} ~CFactory(){} private: long m_cRef; }; HRESULT CFactory::QueryInterface(const IID& iid,void** ppv){ if((iid == IID_IUnknown) || (iid == IID_IClassFactory)){ *ppv = static_cast<IClassFactory*>(this); } else{ *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; } ULONG _stdcall CFactory::AddRef(){ return InterlockedIncrement(&m_cRef); } ULONG _stdcall CFactory::Release(){ if(InterlockedDecrement(&m_cRef) == 0){ delete this; return 0; } return m_cRef; } HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,void** ppv){ if((pUnknownOuter != NULL) && (iid != IID_IUnknown)){ return CLASS_E_NOAGGREGATION; } CB* pB = new CB(pUnknownOuter); if(pB == NULL){ return E_OUTOFMEMORY; } HRESULT hr = pB->NondelegatingQueryInterface(iid,ppv); pB->NondelegatingRelease(); return hr; } HRESULT CFactory::LockServer(BOOL bLock){ if(bLock){ InterlockedIncrement(&g_cServerLocks); } else{ InterlockedDecrement(&g_cServerLocks); } return S_OK; } STDAPI DllCanUnloadNow(){ if((g_cComponents == 0) && (g_cServerLocks == 0)){ return S_OK; } else{ return S_FALSE; } } STDAPI DllGetClassObject(const CLSID& clsid,void** ppv){ if(clsid != CLSID_Component2){ return CLASS_E_CLASSNOTAVAILABLE; } CFactory* pFactory = new CFactory; if(pFactory == NULL){ return E_OUTOFMEMORY; } HRESULT hr = pFactory ->QueryInterface(iid,ppv); pFactory->Release(); return hr; } STDAPI DllRegisterServer(){ return RegisterServer(g_hModule,CLSID_Component2,g_szProgID); } STDAPI DllUnregisterServer(){ return UnregisterServer(CLSID_Component2,g_szProgID); } BOOL API ENTRY DllMain(HANDLE hModule,void* lpReserved){ if(dwReason == DLL_PROCESS_ATTACH){ g_hModule = hModule; } return TRUE; } 此例中,外部组件只是聚合了内部组件实现的一个接口,客户能够访问的内部组件将只有IY。 当外部组件需要聚合内部组件实现的多个接口时: 避免使用盲目聚合,为避免冲突,有两种方法:其一,元接口。其二,将外部组件和客户或外部组件和内部组件作为匹配对来实现。 组件的内部状态信息: COM中的所有功能都是通过借口来实现的。因此,为提供内部状态信息,可以加上一个新的接口。此接口可以给外部组件提供一些状态信息,帮助开发人员实现对组件的定制
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |