Condividi tramite


Supporto di interfacce Dual o Dispatch

Analogamente all'interfaccia dispatch, tutte le interfacce duali devono ereditare da IDispatch, che delega tutte le funzioni IDispatch (GetIDsOfNames, Invoke, GetTypeInfo, GetTypeInfoCount) all'IDispatch dell'aggregatore (ADSI). Per delegare, un oggetto di estensione deve eseguire una query per l'IDispatch dell'aggregatore, chiamare il metodo aggregatore appropriato e rilasciare il puntatore dopo l'uso.

Se l'estensione può essere un componente autonomo, verificare che sia aggregato. In tal caso, reindirizzare le funzioni dispatch al IDispatch dell'aggregatore, altrimenti è possibile chiamare l'implementazione interna di IDispatch oppure chiamare l'implementazione di IADsExtension.

L'esempio di codice seguente illustra come reindirizzare la chiamata IDispatch al IDispatch dell'aggregatore. In questo esempio di codice si presuppone che la variabile membro m_pOuterUnknown sia stata inizializzata nel puntatore IUnknown dell'aggregatore.

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

I writer di estensioni sono fortemente invitati a supportare interfacce duali anziché interfacce dispatch nei relativi oggetti di estensione. Un'interfaccia doppia consente a un client di avere accesso più veloce, purché nel client sia abilitato l'accesso alla tabella virtuale. Per altre informazioni, vedere Associazione tardiva e Accesso alla tabella virtuale nel modello di estensione ADSI. In base al modello corrente, l'implementazione di interfacce duali non deve essere più difficile rispetto all'implementazione di interfacce dispatch.