COM 对象聚合

前端之家收集整理的这篇文章主要介绍了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,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,{b1,b8}}

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

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

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