Поделиться через


Поддержка двух или диспетчерских интерфейсов

Как и интерфейс отправки, все два интерфейса должны наследоваться от IDispatch, который делегирует все его функции IDispatch (GetIDsOfNames, Invoke, GetTypeInfo, GetTypeInfoCount) обратно в IDispatch агрегатора (ADSI). Чтобы делегировать, объект расширения должен запрашивать IDispatch агрегатора, вызывать соответствующий метод агрегатора и освобождать указатель после использования.

Если расширение может быть автономным компонентом, убедитесь, что оно агрегировано. В этом случае перенаправьте функции диспетчера в IDispatch агрегатора, в противном случае можно вызвать внутреннюю реализацию IDispatch или вызвать реализацию IADsExtension.

В следующем примере кода показано, как перенаправить вызов IDispatch в IDispatch агрегатора. В этом примере кода предполагается, что переменная элемента m_pOuterUnknown была инициализирована в указатель IUnknown агрегатора.

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

Записи расширений настоятельно рекомендуется поддерживать двойные интерфейсы вместо интерфейсов диспетчеризации в своих объектах расширения. Двойной интерфейс позволяет клиенту быстрее получать доступ, если в клиенте включен доступ к vtable. Дополнительные сведения см. в разделе "Поздняя привязка" и "Vtable Access" в модели расширения ADSI. На основе текущей модели реализация двух интерфейсов не должна быть более сложной, чем реализация интерфейсов диспетчера.