无论是对象聚合或是对象包容,其作用都是组件的复用,使用环境是这样的,有组件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,var,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,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}

MIDL_DEFINE_GUID(IID, IID_Isome,0xDB21B3C7,0xF4EC,0x4152,0x9B,0xFB,0xE5,0xC3,0xC3,0xB8,0x4D,0x91);

而是加入了#include"D:\project\neo\neo\neo_i.c"定义文件,最后测试成功!一天啊同学们....