COM 对象聚合

无论是对象聚合或是对象包容,其作用都是组件的复用,使用环境是这样的,有组件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"定义文件,最后测试成功!一天啊同学们....


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值