您的位置:首页 > 其它

ATL 实现com的聚合

2014-06-11 17:32 253 查看
com聚合是包容的一种特例,目的是最大化的实现功能模块话,降低组件间的耦合性。

第一步:

通过ATL创建com外部组件TestOutCom.dll,在其内部创建接口包装类CCMyOuterCom,并实现其对应的接口ICMyOuterCom,注意默认选择“聚合”(这点很重要,后面我们会详细解说)







在“聚合”选项中:

勾选“是”,则按照默认生成支持聚合的包装类

勾选“否”,则包装类头文件CMyOuterCom.h,在公开接口列表字段(“BEGIN_COM_MAP”)前面会出现 “DECLARE_NOT_AGGREGATABLE(CCMyOuterCom)

勾选“只能创建为聚合”,则包装类头文件CMyOuterCom.h,在公开接口列表字段(“BEGIN_COM_MAP”)前面会出现 “
DECLARE_ONLY_AGGREGATABLE(CCMyOuterCom)

和聚合相关的宏有三个:

DECLARE_NOT_AGGREGATABLE //不支持聚合

DECLARE_AGGREGATABLE //支持聚合

DECLARE_ONLY_AGGREGATABLE //仅支持聚合

三个宏定义如下:

[cpp] view
plaincopy

#define DECLARE_NOT_AGGREGATABLE(x) public:/

typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;

#define DECLARE_AGGREGATABLE(x) public:/

typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;

#define DECLARE_ONLY_AGGREGATABLE(x) public:/

typedef ATL::CComCreator2< ATL::CComFailCreator<E_FAIL>, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;

通过宏的定义可以清楚的看到组件的创建过程。

如果组件不支持聚合,那么T2就是 CComFailCreator<CLASS_E_NOAGGREGATION>。若想创建被聚合情况下的组件,那么就会调用 CComFailCreator::CreateInstance(),然后直接返回参数CLASS_E_NOAGGREGATION。同样,如果组件仅支持聚合,那么T1就是CComFailCreator<E_FAIL>,创建时直接返回E_FAIL。

CComAggObject提供了两个IUnknown的实现。一个实现用于转发调用给外部的控制对象,包含它的生命期和身份标识符,另一个用于实现外部控制对象的私有用途,用于维护内部对象的生命期和接口查询。CComAggObject拥有IUnknown接口的两套实现方式,一种是通过CComObjectRootEx直接继承获得,一种是通过成员变量CComContainedObject<contained> m_contained间接获得。m_contained变量用于维护m_pOuterUnknown成员。

另外也可以使用CComPloyObject来支持组件聚合。

之后点击“完成”;并在接口中实现“GetOuterMethord”方法,方便后期测试和使用。当然也可以加入自己项目中需要的函数






完成接口方法的创建,此时我们的外部组件就创建成功了。



第二步:

按照第一步的方法,同样通过ATL创建com建内部组件TestInnerCom.dll,在其内部创建接口包装类CCMyInnerCom,并实现其对应的接口ICMyInnerCom,在ICMyInnerCom实现实现“GetInnerMethord”方法。



最后两个组件中包装类的结构分别如下





第三步:

为了实现聚合操作,需要对外部组件的包装类的头文件CMyOuterCom.h进行修改。而对内部组件不需要进行任何操作。

加入对内部组件接口信息的文件引用:

#include "..\TestInnerCom\TestInnerCom_i.h"

#include "..\TestInnerCom\TestInnerCom_i.c"


增加变量IUnknown * m_InnerComUnknown;

修改组件对客户程序公布的接口列表:

BEGIN_COM_MAP(CCMyOuterCom)

COM_INTERFACE_ENTRY(ICMyOuterCom)

COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_InnerComUnknown) //声明聚合,只有公开了外面才能通过IUnknown
指针来访问内部组件的接口

COM_INTERFACE_ENTRY(IDispatch)

END_COM_MAP()

修改外部组件包装类的接口构造函数:

DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULT FinalConstruct()

{

HRESULT hr = CoCreateInstance(CLSID_CMyInnerCom,

this,//GetControllingUnknown(),

CLSCTX_ALL,

IID_IUnknown,

(void**)&m_InnerComUnknown);

if (FAILED(hr))

{

return E_FAIL ;

}

return S_OK;

}

修改后的外部组件包装类如下,



第四步:编写测试代码

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: