一个Java基础练习

com聚合是包容的一种特例,目的是最大化的实现功能模块话,降低组件间的耦合性。

第一步:

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

   一个Java基础练习

  

  一个Java基础练习


  一个Java基础练习


   在“聚合”选项中:

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

                  勾选“否”,则包装类头文件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”方法,方便后期测试和使用。当然也可以加入自己项目中需要的函数一个Java基础练习


   一个Java基础练习


      一个Java基础练习

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

      一个Java基础练习


第二步:

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

       一个Java基础练习


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

       一个Java基础练习


一个Java基础练习



第三步:

    为了实现聚合操作,需要对外部组件的包装类的头文件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;
}

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

   一个Java基础练习


  第四步:编写测试代码

    一个Java基础练习

    

一个Java基础练习,布布扣,bubuko.com

一个Java基础练习

上一篇:295.博客园win&苹果PC客户端开源项目整理


下一篇:Android 开发 框架系列 OkHttp拦截器