Compatibilidad con interfaces duales o de distribución
Al igual que la interfaz de distribución, todas las interfaces duales deben heredar de IDispatch, que delegue todas sus funciones IDispatch (GetIDsOfNames, Invoke, GetTypeInfo, GetTypeInfoCount) a la IDispatch del agregador (ADSI). Para delegar, un objeto de extensión debe consultar el IDispatch del agregador, llamar al método agregador adecuado y liberar el puntero después de su uso.
Si la extensión puede ser un componente independiente, compruebe que se agrega. Si es así, vuelva a enrutar las funciones de envío al IDispatch del agregador; de lo contrario, puede llamar a la implementación interna de IDispatch o puede llamar a la implementación de IADsExtension.
En el ejemplo de código siguiente se muestra cómo volver a enrutar la llamada IDispatch a IDispatch del agregador. En este ejemplo de código se supone que la variable miembro m_pOuterUnknown se ha inicializado en el puntero IUnknown del 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;
}
Se recomienda encarecidamente que los escritores de extensiones admitan interfaces duales en lugar de interfaces de envío en sus objetos de extensión. Una interfaz dual permite a un cliente tener un acceso más rápido, siempre y cuando el acceso a vtable esté habilitado en el cliente. Para obtener más información, vea Enlace en tiempo de ejecución frente a acceso vtable en el modelo de extensión ADSI. En función del modelo actual, la implementación de interfaces duales no debe ser más difícil que la implementación de interfaces de distribución.