包容和聚合(COM技术内幕笔记五)

包容和聚合:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

   包容和聚合实际上是使一个组件使用另外一个组件的一种技术。在包容的情况下,外部组件将包含内部组件。在聚合的情况下,外部组件聚合内部组件。

   在此设想一下,外部组件是我们的要实现的组件,而内部组件是其它要重用的组件。

    包容是外部组件包含指向内部组件接口的指针.外部组件相对来说是内部组件的一个客户,它将使用内部组件的接口来实现它自己的接口.

    聚合是包容的一个特例,当一个外部组件聚合了某个内部组件的一个接口时,它并没有像包容那样重新实现此接口并明确地将调用请求转发给内部组件。相反,外部组件将直接把内部件的接口指针返回给客户。

如何使用包容:

   在前一节,建立了一个组件CA,其实现了IXIY接口。在这一节,暂时把其看作是一内部组件。我们要使用其对IY接口的函数实现
   
新建一个DLL项目,新建一接口IX,新建一个组件的CLSID。另外,导入CA项目IFACE.h中的IY接口IIDCA组件的CLSID。如下所示:
   

None.gif extern   " C "
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
// {3CA3B6D4-799C-4d5d-BF3A-373C4EECE925}  此IX是新建的IID
InBlock.gif
    static const IID IID_IX = 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif0x3ca3b6d40x799c0x4d5ddot.gif0xbf0x3a0x370x3c0x4e0xec0xe90x25 } };
InBlock.gif    
InBlock.gif    
// {41A5F090-B33A-4ae8-A1BB-EF2D0B4F8B0E} //此IY是从CA中IID_IY的复制
InBlock.gif
    static const IID IID_IY = 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif0x41a5f0900xb33a0x4ae8dot.gif0xa10xbb0xef0x2d0xb0x4f0x8b0xe } };
ExpandedBlockEnd.gif}

None.gif    
//  {3D29721C-8D93-4c24-A8A5-4CE01FD9FD00}   这是CB组件新建的CLSID
None.gif
     static   const  CLSID CLSID_CTANINFACE  =  
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif 0x3d29721c0x8d930x4c24dot.gif0xa80xa50x4c0xe00x1f0xd90xfd0x0 } } ;
None.gif
None.gif    
//  {282D8F98-BC89-43d5-9225-0B1BB479CBDE}  这是CA组件复制过来的CLSID
None.gif
     static   const  CLSID CLSID_Component1  =  
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif 0x282d8f980xbc890x43d5dot.gif0x920x250xb0x1b0xb40x790xcb0xde } } ;
None.gif


在组件 CB 实现的时候,添加一成员变量:
private:
   IY* m_pIY;

IY接口的Fy函数的实现,与组件CA不同:

Virtual void __stdcall CB::Fy()

{

              m_pIY->Fy();

}


对组件CB新增一成员函数 HRESULT Init();

None.gif HRESULT CB::Init()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    trace(
"Create Contained component.");
InBlock.gif    
//CLISD_Component1为组件CA的CLSID
InBlock.gif
    HRESULT hr = ::CoCreateInstance(CLSID_Component1, 
InBlock.gif                                    NULL,
InBlock.gif                                    CLSCTX_INPROC_SERVER,
InBlock.gif                                     IID_IY,(
void**)&m_pIY);   
InBlock.gif
InBlock.gif    
if(FAILED(hr))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        trace(
"Could not create contained components");
InBlock.gif        
return E_FAIL;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
InBlock.gif        
return S_OK;
ExpandedBlockEnd.gif}

None.gif


至于CB的其它实现和CA相同,暂不累叙,如有不清楚的概念请看前一节。


在组件 CB CFactory::CreateInstance 函数中加入对 Init 函数的调用:
None.gif HRESULT __stdcall CFactory::CreateInstance(IUnknown *  pUnknownOuter,   const  IID &  iid,   void **  ppv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    CA
* pA = new CA();
InBlock.gif    
if(pA == NULL)
InBlock.gif        
return E_OUTOFMEMORY;
InBlock.gif
InBlock.gif    HRESULT hr 
= pA->Init();
InBlock.gif    
if(FAILED(hr))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        pA
->Release();
InBlock.gif        
return hr;
ExpandedSubBlockEnd.gif    }

InBlock.gif    hr 
= pA->QueryInterface(iid,ppv);
InBlock.gif    pA
->Release();
InBlock.gif    
return hr;
ExpandedBlockEnd.gif}

None.gif


     在此,就实现了组件CB对组件CA的包容。CB没有自己去实现基类IY的Fy()函数,而是把这个任务交给了组件CA对于Fy()函数的实现。一切的一切都是通过组件CB中的Init函数。通过CoCreateInstance查询组件CA的IY接口。然后返回IY指针,赋给CB的私有成员m_pIY。
    通过对于m_pIY的包容,实现了组件的复用。

   至于组件的聚合,下一节再叙。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值