Unterstützen von Dual- oder Dispatch-Schnittstellen

Wie die Dispatchschnittstelle müssen alle dualen Schnittstellen von IDispatcherben, das alle seine 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 wieder frei geben.

Wenn die Erweiterung eine eigenständige Komponente sein kann, überprüfen Sie, ob sie aggregiert ist. Falls ja, werden die Dispatchfunktionen an das IDispatch des Aggregators umgeleitet. 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 das IDispatch des Aggregators umleiten. In diesem Codebeispiel wird davon ausgegangen, dass die Membervariable m _ pOuterUnknown mit dem 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;
}

Erweiterungsautoren wird dringend empfohlen, duale Schnittstellen anstelle von Dispatchschnittstellen 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äte Bindung im Vergleich zum Vtable-Zugriff im ADSI-Erweiterungsmodell. Basierend auf dem aktuellen Modell sollte die Implementierung von dualen Schnittstellen nicht schwieriger als die Implementierung von Dispatchschnittstellen sein.