Ereditarietà, aggregazione e contenimento

Il riutilizzo di COM in .NET Framework è possibile tramite ereditarietà. I tipi COM partecipano al meccanismo dell'ereditarietà come classi base. Utilizzare i modelli di ereditarietà, aggregazione e contenimento nelle seguenti circostanze:

Modello

Da utilizzare per

Ereditarietà

Esporre l'oggetto gestito come oggetto esterno.

Aggregazione

Consentire all'oggetto esterno di esporre l'implementazione di un'interfaccia di un altro oggetto senza apportarvi modifiche.

Contenimento

Consentire all'oggetto esterno di modificare il comportamento dell'oggetto interno.

Ereditarietà

Quando le interfacce gestite vengono esposte a COM, estendono sempre IUnknown o IDispatch, anche quando l'interfaccia è ereditata da un'altra interfaccia sul lato gestito. La stessa regola vale per le interfacce della classe che vengono generate per le classi gestite.

.NET Framework estende il modello di riutilizzabilità COM aggiungendo l'ereditarietà dell'implementazione. I tipi gestiti possono derivare direttamente o indirettamente da una coclasse COM. Più specificamente, possono derivare dal Runtime Callable Wrapper generato dal runtime. I tipi derivati possono esporre tutti i metodi e le proprietà dell'oggetto COM così come i metodi e le proprietà implementati nel codice gestito. L'oggetto risultante è implementato parte nel codice gestito e parte nel codice non gestito.

Per essere qualificata come classe base, la coclasse deve:

I tipi gestiti possono estendere l'RCW della coclasse che si sta qualificando ed effettuare l'override dei metodi forniti dall'oggetto base. Se si desidera effettuare l'override di tutti i metodi di un'interfaccia, occorre effettuare l'override di ciascun metodo base.

Un tipo gestito eredita da un RCW allo stesso modo in cui eredita da un oggetto base gestito. Nell'esempio di codice che segue, la classe gestita Catapult deriva da AcmeLib.Slingshot, un tipo COM.

#using "AcmeLib.dll"    // Provides definition of Slingshot.

__gc class Catapult : public AcmeLib.Slingshot  // Extends the COM type.
{
    // Delegates to base implementation.
    Load() { //… };  
   
    Fire()               
    {
        // Engages in some behavior before delegating to the base 
        // implementation.
        Slingshot::Fire();
    }

    // The Aim method needs to be overridden.
    Aim() { //… }         
}
Catapult *cp = new Catapult();

// Calls derived implementation.
cp->Load();
// Calls base implementation.
cp->Aim();
// Calls derived which delegates to base.
cp->Fire();

Aggregazione

Per esporre le interfacce di una classe COM come se queste fossero implementate su una seconda classe COM, la seconda classe aggrega la prima. Un oggetto COM può aggregare un oggetto .NET. In questo caso tutte le interfacce dell'oggetto, compresa l'interfaccia della classe, saranno disponibili tramite l'oggetto esterno. L'oggetto .NET interno delega le chiamate dei propri metodi IUnknown all'IUnknown superiore.

L'aggregazione è leggermente più complessa del contenimento (descritto nella sezione che segue). La si usa tipicamente per consentire all'oggetto esterno di esporre l'implementazione di un'interfaccia di un altro oggetto senza apportarvi modifiche. Tutti gli oggetti gestiti supportano automaticamente l'aggregazione di tipo COM in cui l'oggetto gestito è utilizzato come oggetto interno. Per aggregare un oggetto gestito, l'oggetto esterno non gestito crea l'oggetto interno gestito chiamando CoCreateInstance e passando l'IUnknown dell'oggetto esterno come parametro OuterUnknown. Quando un IUnknown esterno viene passato a un oggetto gestito durante la costruzione, l'oggetto gestito inserisce l'interfaccia nella cache e la utilizza come descritto di seguito:

  • L'oggetto esterno si basa sull'IUnknown non delegante dell'IUnknown interno. Il comportamento dell'IUnknown non delegante corrisponde a quello di un IUnknown normale. Avrà pertanto esito positivo se l'interfaccia viene implementata dall'oggetto e negativo in caso contrario. La chiamata non viene inoltrata dall'IUnknown non delegante all'oggetto esterno.

  • Se l'oggetto interno riceve una richiesta per un'interfaccia che non supporta, rimanda la chiamata all'interfaccia IUnknown dell'oggetto esterno.

  • Tutte le chiamate ai metodi QueryInterface, AddRef e Release dell'oggetto interno vengono delegate all'IUnknown.

Questi tre comportamenti rendono possibile l'aggregazione di qualsiasi oggetto gestito. Con questo tipo di aggregazione è possibile avere un singolo oggetto COM implementato in parte nel codice gestito (la parte interna) e in parte nel codice non gestito (la parte esterna).

Contenimento

Un oggetto .NET può contenere un oggetto COM importandone i metadati in un assembly .NET, quindi dichiarando un membro dati di quel tipo all'interno di un'altra classe. Come con il normale contenimento COM, è possibile chiamare le interfacce dell'oggetto COM tramite le proprie implementazioni relative, ma l'oggetto contenuto non viene esposto al di fuori della classe. Il contenimento è più semplice dell'aggregazione. Solitamente si utilizza il contenimento quando occorre che l'oggetto esterno modifichi il comportamento dell'oggetto interno. A tal fine, l'oggetto esterno crea semplicemente un'istanza dell'oggetto interno nel proprio costruttore e, a seconda delle esigenze, delega le chiamate all'oggetto interno. L'oggetto esterno può stabilire quali chiamate delegare e quali chiamate gestire invece direttamente. Non vi sono requisiti particolari senza i quali il runtime non permette il contenimento di determinati oggetti.

Un oggetto COM può anche contenere un oggetto .NET. Il comportamento rispetto ai client dell'oggetto COM è esattamente identico a quello che si sarebbe ottenuto se l'oggetto contenuto fosse stato un qualsiasi altro oggetto COM.

Vedere anche

Concetti

Esposizione di componenti COM a .NET Framework

Esposizione di componenti .NET Framework a COM

Altre risorse

Interoperabilità COM avanzata