Suporte a interfaces duplas ou de despacho

Como a interface de despacho, todas as interfaces duplas devem herdar de IDispatch, que delega todas as suas funções IDispatch (GetIDsOfNames, Invoke, GetTypeInfo, GetTypeInfoCount) de volta para o IDispatch do agregador (ADSI). Para delegar, um objeto de extensão deve consultar o IDispatch do agregador, chamar o método agregador apropriado e liberar o ponteiro após o uso.

Se a extensão puder ser um componente autônomo, verifique se ela está agregada. Em caso afirmativo, redirecione as funções de despacho para o IDispatch do agregador, caso contrário, você pode chamar sua implementação interna de IDispatch ou pode chamar sua implementação de IADsExtension.

O exemplo de código a seguir mostra como redirecionar a chamada IDispatch para o IDispatch do agregador. Este exemplo de código pressupõe que a variável de membro m_pOuterUnknown foi inicializada para o ponteiro IUnknown do agregador.

/////////////////////////////////////////////////// 
// Delegating IDispatch Methods to the aggregator
///////////////////////////////////////////////////
STDMETHODIMP MyExtension::GetTypeInfoCount(UINT* pctinfo)
{
    IDispatch *pDisp = NULL;
    HRESULT    hr = S_OK;
    hr = m_pOuterUnknown->QueryInterface( IID_IDispatch, (void**) &pDisp );
    if ( SUCCEEDED(hr) )
    {
        hr = pDisp->GetTypeInfoCount( pctinfo );
        pDisp->Release();
    }
    return hr;
}
 
 
STDMETHODIMP MyExtension::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
    IDispatch *pDisp = NULL;
    HRESULT    hr = S_OK;
    hr = m_pOuterUnknown->QueryInterface( IID_IDispatch, (void**) &pDisp );
    if ( SUCCEEDED(hr) )
    {
        hr = pDisp->GetTypeInfo( itinfo, lcid, pptinfo );
        pDisp->Release();
    }
    
    return hr;
}
 
STDMETHODIMP MyExtension::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
{
    IDispatch *pDisp = NULL;
    HRESULT    hr = S_OK;
    hr = m_pOuterUnknown->QueryInterface( IID_IDispatch, (void**) &pDisp );
    if ( SUCCEEDED(hr) )
    {
        hr = pDisp->GetIDsOfNames( riid, rgszNames, cNames, lcid, 
                 rgdispid);
        pDisp->Release();
    }
    
    return hr;
 
}
 
STDMETHODIMP MyExtension::Invoke(DISPID dispidMember, REFIID riid,
        LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* 
                pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
    IDispatch *pDisp = NULL;
    HRESULT    hr = S_OK;
    hr = m_pOuterUnknown->QueryInterface( IID_IDispatch, (void**) &pDisp );
    if ( SUCCEEDED(hr) )
    {
        hr = pDisp->Invoke( dispidMember, riid, lcid, wFlags, 
                 pdispparams, pvarResult, pexcepinfo, puArgErr);
        pDisp->Release();
    }
    
    return hr;
}

Os gravadores de extensão são fortemente encorajados a oferecer suporte a interfaces duplas em vez de interfaces de despacho em seus objetos de extensão. Uma interface dupla permite que um cliente tenha acesso mais rápido, desde que o acesso vtable esteja habilitado no cliente. Para obter mais informações, consulte Late Binding vs. Vtable Access no modelo de extensão ADSI. Com base no modelo atual, a implementação de interfaces duplas não deve ser mais difícil do que a implementação de interfaces de despacho.