Condividi tramite


QueryInterface: Spostamento in un oggetto

Dopo aver ottenuto un puntatore iniziale a un'interfaccia su un oggetto, COM ha un meccanismo molto semplice per scoprire se l'oggetto supporta un'altra interfaccia specifica e, in tal caso, per ottenere un puntatore a esso. Per informazioni sul recupero di un puntatore iniziale a un'interfaccia in un oggetto, vedere Recupero di un puntatore a un oggetto. Questo meccanismo è il metodo QueryInterface dell'interfaccia IUnknown. Se l'oggetto supporta l'interfaccia richiesta, il metodo deve restituire un puntatore a tale interfaccia. Ciò consente a un oggetto di spostarsi liberamente tra le interfacce supportate da un oggetto. QueryInterface separa la richiesta "Si supporta un determinato contratto?" dall'uso ad alte prestazioni di tale contratto dopo che le trattative hanno avuto esito positivo.

Quando un client ottiene inizialmente l'accesso a un oggetto, tale client riceverà almeno un puntatore di interfaccia IUnknown (l'interfaccia più fondamentale) tramite cui può controllare la durata dell'oggetto, indicando all'oggetto quando viene eseguito usando l'oggetto e richiamare QueryInterface. Il client è programmato per chiedere a ogni oggetto che riesce a eseguire alcune operazioni, ma l'interfaccia IUnknown non ha funzioni per tali operazioni. Queste operazioni vengono invece espresse tramite altre interfacce. Il client è quindi programmato per negoziare con gli oggetti per tali interfacce. In particolare, il client chiamerà QueryInterface per chiedere a un oggetto un'interfaccia tramite cui il client può richiamare le operazioni desiderate.

Poiché l'oggetto implementa QueryInterface, può accettare o rifiutare la richiesta. Se l'oggetto accetta la richiesta del client, QueryInterface restituisce un nuovo puntatore all'interfaccia richiesta al client. Tramite tale puntatore di interfaccia, il client ha accesso ai metodi di tale interfaccia. Se, d'altra parte, l'oggetto rifiuta la richiesta del client, QueryInterface restituisce un puntatore Null, un errore, e il client non dispone di un puntatore attraverso il quale chiamare le funzioni desiderate. In questo caso, il cliente deve gestire correttamente tale possibilità. Si supponga, ad esempio, che un client disponga di un puntatore all'interfaccia A su un oggetto e richieda interfacce B e C. Si supponga anche che l'oggetto supporti l'interfaccia B ma non supporti l'interfaccia C. Il risultato è che l'oggetto restituisce un puntatore a B e segnala che C non è supportato.

Un punto chiave è che quando un oggetto rifiuta una chiamata a QueryInterface, è impossibile che il client chieda all'oggetto di eseguire le operazioni espresse tramite l'interfaccia richiesta. Un client deve avere un puntatore all'interfaccia per richiamare i metodi in tale interfaccia. Se l'oggetto rifiuta di fornire il puntatore richiesto, il client deve essere preparato a farlo senza, non eseguendo alcuna operazione che aveva intenzione di eseguire con tale oggetto o tentando di eseguire il fallback su un altro, forse meno potente, interfaccia. Questa funzionalità di funzionalità COM funziona bene rispetto ad altri sistemi orientati agli oggetti in cui non è possibile sapere se una funzione funzionerà fino a quando non si chiama tale funzione e, anche allora, la gestione degli errori è incerta. QueryInterface offre un modo affidabile e coerente per sapere se un oggetto supporta un'interfaccia prima di tentare di chiamare i relativi metodi.

Il metodo QueryInterface fornisce inoltre un modo affidabile e affidabile per un oggetto per indicare che non supporta un determinato contratto. Ciò significa che, se in una chiamata a QueryInterface uno chiede a un oggetto "vecchio" se supporta un'interfaccia "nuova" (una, ad esempio, che è stata inventata dopo la spedizione dell'oggetto precedente), l'oggetto precedente sarà affidabile, senza causare un arresto anomalo, rispondere "no". La tecnologia che supporta questo è l'algoritmo in base al quale vengono allocati ID. Anche se questo può sembrare un piccolo punto, è estremamente importante per l'architettura complessiva del sistema e la possibilità di interrogare gli elementi legacy su nuove funzionalità è, sorprendentemente, una funzionalità non presente nella maggior parte delle altre architetture di oggetti.

Uso e implementazione di IUnknown