COM学习笔记(十一 ):聚合的一个完整例子

前端之家收集整理的这篇文章主要介绍了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中的所有功能都是通过借口来实现的。因此,为提供内部状态信息,可以加上一个新的接口。此接口可以给外部组件提供一些状态信息,帮助开发人员实现对组件的定制





猜你在找的设计模式相关文章