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中的所有功能都是通过借口来实现的。因此,为提供内部状态信息,可以加上一个新的接口。此接口可以给外部组件提供一些状态信息,帮助开发人员实现对组件的定制





相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...