ATL 实现com的聚合

4 篇文章 0 订阅
3 篇文章 0 订阅

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 //仅支持聚合
三个宏定义如下:

  1. #define DECLARE_NOT_AGGREGATABLE(x) public:/  
  2.      typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;  
  3. #define DECLARE_AGGREGATABLE(x) public:/  
  4.      typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;  
  5. #define DECLARE_ONLY_AGGREGATABLE(x) public:/  
  6.      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;
}

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

   


  第四步:编写测试代码

    

    

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值