Condividi tramite


Uso degli assembly di interoperabilità di Visual Studio

Gli assembly di interoperabilità di Visual Studio consentono alle applicazioni gestite di accedere alle interfacce COM che forniscono l'estendibilità di Visual Studio. Esistono alcune differenze tra le interfacce COM dritte e le relative versioni di interoperabilità. Ad esempio, gli HRESULT sono in genere rappresentati come valori int e devono essere gestiti nello stesso modo delle eccezioni e i parametri (in particolare i parametri out) vengono trattati in modo diverso.

Gestione di valori HRESULT restituiti al codice gestito da COM

Quando si chiama un'interfaccia COM dal codice gestito, esaminare il valore HRESULT e generare un'eccezione, se necessario. La classe ErrorHandler contiene il metodo ThrowOnFailure, che genera un'eccezione COM, a seconda del valore HRESULT passato.

Per impostazione predefinita, ThrowOnFailure genera un'eccezione ogni volta che viene passato un valore HRESULT minore di zero. Nei casi in cui tali valori HRESULT sono valori accettabili e non deve essere generata alcuna eccezione, i valori HRESULT aggiuntivi devono essere passati a ThrowOnFailure dopo essere stati testati. Se il valore HRESULT testato corrisponde a qualsiasi valore HRESULT passato in modo esplicito a ThrowOnFailure, non viene generata alcuna eccezione.

Nota

La VSConstants classe contiene costanti per HRESULTS comuni, ad esempio e E_NOTIMPL, e Visual Studio HRESULTS, ad esempio S_OK VS_E_INCOMPATIBLEDOCDATA e VS_E_UNSUPPORTEDFORMAT. VSConstants fornisce inoltre i metodi Succeeded e Failed, che corrispondono alle macro SUCCEEDED e FAILED in COM.

Si consideri, ad esempio, la seguente chiamata di funzione, in cui E_NOTIMPL è un valore restituito accettabile, ma qualsiasi altro valore HRESULT minore di zero rappresenta un errore.

int hr = MyInterface.MyFunction(cmdID);
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOTIMPL);

Se ci sono più valori restituiti accettabili, è sufficiente aggiungere gli ulteriori valori HRESULT all'elenco nella chiamata a ThrowOnFailure.

int hr = MyInterface.MyFunction(cmdID);
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOINTERFACE, VSConstants.E_NOTIMPL);

Restituzione di valori HRESULT a COM dal codice gestito

Se non si verifica alcuna eccezione, il codice gestito restituisce S_OK alla funzione COM che lo ha chiamato. L'interoperabilità COM supporta eccezioni comuni fortemente tipizzate nel codice gestito. Ad esempio, un metodo che riceve un argomento null non accettabile, genera un'eccezione ArgumentNullException.

Se non si è certi di quale eccezione generare, ma si conosce il valore HRESULT che si vuole restituire a COM, è possibile usare il metodo ThrowExceptionForHR per generare un'eccezione appropriata. Ciò funziona anche con un errore non standard, ad esempio VS_E_INCOMPATIBLEDOCDATA. ThrowExceptionForHR prova a eseguire il mapping tra valore HRESULT passato e un'eccezione fortemente tipizzata. Se ciò non è possibile, genera un'eccezione COM generica. Il risultato finale è che il valore HRESULT passato a ThrowExceptionForHR dal codice gestito viene restituito alla funzione COM che lo ha chiamato.

Nota

Le eccezioni compromettono le prestazioni e servono per indicare condizioni anomale dei programmi. Le condizioni che si verificano spesso devono essere gestite inline, invece di generare un'eccezione.

Parametri IUnknown passati come Type void**

Cercare i parametri [out] definiti come tipo void ** nell'interfaccia COM, ma definiti come [``iid_is``] nel prototipo del metodo assembly di interoperabilità di Visual Studio.

In alcuni casi, un'interfaccia COM genera un IUnknown oggetto e l'interfaccia COM la passa come tipo void **. Queste interfacce sono particolarmente importanti perché se la variabile è definita come [out] nel file IDL, l'oggetto IUnknown viene conteggiato con il AddRef metodo . Se l'oggetto non viene gestito correttamente, si verifica una perdita di memoria.

Nota

Un IUnknown oggetto creato dall'interfaccia COM e restituito in una variabile [out] causa una perdita di memoria se non viene rilasciata in modo esplicito.

I metodi gestiti che gestiscono tali oggetti devono essere considerati IntPtr come puntatore a un IUnknown oggetto e chiamare il GetObjectForIUnknown metodo per ottenere l'oggetto. Il chiamante deve quindi eseguire il cast del valore restituito a qualsiasi tipo appropriato. Quando l'oggetto non è più necessario, chiamare Release per rilasciarlo.

Di seguito è riportato un esempio di chiamata al QueryViewInterface metodo e della gestione corretta dell'oggetto IUnknown :

MyClass myclass;
Object object;
IntPtr pObj;
Guid iid = Typeof(MyClass).Guid;
int hr = windowFrame.QueryViewInterface(ref iid, out pObj);
if (NativeMethods.Succeeded(hr))
{
    try
    {
        object = Marshal.GetObjectForIUnknown(pObj);
        myclass = object;
    }
    finally
    {
        Marshal.Release(pObj);
    }
}
else
{
    // error calling QueryViewInterface
}

Nota

I metodi seguenti sono noti per passare IUnknown puntatori a oggetti come tipo IntPtr. Gestirli come descritto in questa sezione.

Parametri facoltativi [out]

Cercare i parametri definiti come tipo di dati [out] (int, objecte così via) nell'interfaccia COM, ma definiti come matrici dello stesso tipo di dati nel prototipo del metodo assembly di interoperabilità di Visual Studio.

Alcune interfacce COM, ad esempio GetCfgs, considerano i parametri [out] come facoltativi. Se un oggetto non è obbligatorio, queste interfacce COM restituiscono un null puntatore come valore di tale parametro anziché creare l'oggetto [out]. Questo si verifica per motivi strutturali. Per queste interfacce, null i puntatori vengono considerati come parte del comportamento corretto del pacchetto VSPackage e non viene restituito alcun errore.

Poiché CLR non consente il valore di un parametro [out] come null, parte del comportamento progettato di queste interfacce non è direttamente disponibile all'interno del codice gestito. I metodi di assembly di interoperabilità di Visual Studio per le interfacce interessate possono risolvere il problema definendo i parametri pertinenti come matrici perché CLR consente il passaggio di null matrici.

Le implementazioni gestite di questi metodi devono inserire una null matrice nel parametro quando non è necessario restituire alcun elemento. In caso contrario, creare una matrice di un elemento del tipo corretto e inserire il valore restituito nella matrice.

I metodi gestiti che ricevono informazioni dalle interfacce con parametri facoltativi [out] ricevono il parametro come matrice. È sufficiente esaminare il valore del primo elemento della matrice. Se non nullè , considerare il primo elemento come se fosse il parametro originale.

Passaggio di costanti nei parametri del puntatore

Cercare i parametri definiti come puntatori [in] nell'interfaccia COM, ma definiti come tipo IntPtr nel prototipo del metodo assembly di interoperabilità di Visual Studio.

Un problema simile si verifica quando un'interfaccia COM passa un valore speciale, ad esempio 0, -1 o -2, anziché un puntatore a un oggetto. A differenza di Visual C++, CLR non consente il cast di costanti come oggetti. L'assembly di interoperabilità di Visual Studio definisce invece il parametro come IntPtr tipo.

Le implementazioni gestite di questi metodi devono sfruttare il fatto che la IntPtr classe abbia entrambi int i costruttori e void * per creare un oggetto IntPtr da un oggetto o da una costante integer, in base alle esigenze.

I metodi gestiti che ricevono IntPtr parametri di questo tipo devono usare gli IntPtr operatori di conversione dei tipi per gestire i risultati. Convertire prima l'oggetto IntPtr in int e testarlo in costanti integer pertinenti. Se nessun valore corrisponde, convertirlo in un oggetto del tipo richiesto e continuare.

Per esempi di questo tipo, vedere OpenStandardEditor e OpenSpecificEditor.

Valori restituiti OLE passati come parametri [out]

Cercare i metodi che hanno un retval valore restituito nell'interfaccia COM, ma che hanno un int valore restituito e un parametro di matrice [out] aggiuntivo nel prototipo del metodo assembly di interoperabilità di Visual Studio. È evidente che questi metodi richiedono una gestione speciale perché i prototipi del metodo assembly di interoperabilità di Visual Studio hanno un altro parametro rispetto ai metodi di interfaccia COM.

Molte interfacce COM che gestiscono l'attività OLE inviano informazioni sullo stato OLE al programma chiamante archiviato nel retval valore restituito dell'interfaccia. Anziché usare un valore restituito, i metodi di assembly di interoperabilità di Visual Studio corrispondenti inviano le informazioni al programma chiamante archiviato in un parametro di matrice [out].

Le implementazioni gestite di questi metodi devono creare una matrice a singolo elemento dello stesso tipo del parametro [out] e inserirla nel parametro . Il valore dell'elemento della matrice deve essere uguale a quello dell'elemento COM retvalappropriato.

I metodi gestiti che chiamano interfacce di questo tipo devono estrarre il primo elemento dalla matrice [out]. Questo elemento può essere considerato come se fosse un retval valore restituito dall'interfaccia COM corrispondente.