ATL 實現com的聚合

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;
}

修改後的外部組件包裝類如下,

   


  第四步:編寫測試代碼

    

    

發佈了35 篇原創文章 · 獲贊 21 · 訪問量 76萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章