Unterstützung von Dual- oder Dispatch-Schnittstellen

Wie die Dispatch-Schnittstelle müssen alle dualen Schnittstellen von IDispatch erben, das alle IDispatch-Funktionen (GetIDsOfNames, Invoke, GetTypeInfo, GetTypeInfoCount) zurück an den IDispatch des Aggregators (ADSI) delegiert. Zum Delegieren sollte ein Erweiterungsobjekt den IDispatch des Aggregators abfragen, die entsprechende Aggregatormethode aufrufen und den Zeiger nach der Verwendung freigeben.

Wenn die Erweiterung eine eigenständige Komponente sein kann, überprüfen Sie, ob sie aggregiert ist. Wenn ja, umleiten Sie die Dispatchfunktionen an den IDispatch des Aggregators. Andernfalls können Sie Ihre interne Implementierung von IDispatch aufrufen, oder Sie können Ihre Implementierung von IADsExtension aufrufen.

Das folgende Codebeispiel zeigt, wie Sie den IDispatch-Aufruf an den IDispatch des Aggregators umleiten. In diesem Codebeispiel wird davon ausgegangen, dass die m_pOuterUnknown Membervariable auf den IUnknown-Zeiger des Aggregators initialisiert wurde.

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

Erweiterungsschreiber werden dringend empfohlen, duale Schnittstellen anstelle von Dispatch-Schnittstellen in ihren Erweiterungsobjekten zu unterstützen. Eine duale Schnittstelle ermöglicht einem Client einen schnelleren Zugriff, solange der vtable-Zugriff im Client aktiviert ist. Weitere Informationen finden Sie unter Spätbindung und Vtable-Zugriff im ADSI-Erweiterungsmodell. Basierend auf dem aktuellen Modell sollte die Implementierung von dualen Schnittstellen nicht schwieriger sein als die Implementierung von Dispatch-Schnittstellen.