Vererbung, Aggregation und Kapselung
COM-Wiederverwendbarkeit in .NET Framework wird durch Vererbung erreicht. COM-Typen können bei der Vererbung als Basisklasse auftreten. Verwenden Sie Modelle der Vererbung, Aggregation oder Kapselung unter folgenden Umständen:
Modell |
Verwendungszweck |
---|---|
Vererbung |
Verfügbarmachen des verwalteten Objekts als äußeres Objekt. |
Aggregation |
Aktivieren des äußeren Objekts, um die Implementierung der Schnittstelle eines anderen Objekts ohne Veränderung verfügbar zu machen. |
Kapselung |
Aktivieren des äußeren Objekts, um das Verhalten des inneren Objekts zu ändern. |
Vererbung
Wenn verwaltete Schnittstellen für COM verfügbar gemacht werden, erweitern sie immer IUnknown oder IDispatch, selbst wenn sie von anderen Schnittstellen der verwalteten Seite geerbt wurden. Dieselbe Regel gilt für die Klassenschnittstellen, die für verwaltete Klassen generiert werden.
Das COM-Modell wird von .NET Framework durch Hinzufügen von Implementierungsvererbung erweitert und dadurch wiederverwendbar. Verwaltete Typen können sowohl direkt als auch indirekt von einer Co-Klasse abgeleitet werden, genauer gesagt, vom RCW (Runtime Callable Wrapper), der durch die Common Language Runtime generiert wird. Der abgeleitete Typ kann alle Methoden und Eigenschaften des COM-Objekts, ebenso wie die in verwaltetem Code implementierten, verfügbar machen. Das resultierende Objekt wird teils in verwaltetem, teils in nicht verwaltetem Code implementiert.
Um als Basisklasse qualifiziert zu sein, muss die Co-Klasse folgende Voraussetzungen erfüllen:
Sie muss in Form von Metadaten definiert sein.
Sie muss erstellt werden können.
Sie muss im COM-spezifischen Sinn aggregationsfähig sein.
Verwaltete Typen können den RCW für eine qualifizierende Co-Klasse erweitern und die durch das Basisobjekt bereitgestellten Methoden überschreiben. Wenn Sie irgendeine Methode überschreiben möchten, müssen Sie dies für alle Basismethoden einer Schnittstelle tun.
Ein verwalteter Typ erbt von einem RCW auf dieselbe Weise wie von einem verwalteten Basisobjekt. Im folgenden Codebeispiel wird die verwaltete Catapult-Klasse von dem COM-Typ AcmeLib.Slingshot abgeleitet.
#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();
Aggregation
Um die Schnittstellen einer COM-Klasse so verfügbar zu machen, als wären sie auf einer zweiten COM-Klasse implementiert worden, wird die erste Klasse von der zweiten zusammengesetzt. Ein .NET-Objekt kann durch ein COM-Objekt zusammengesetzt werden. In diesem Fall sind alle Schnittstellen des Objekts, auch seine Klassenschnittstelle, durch das äußere Objekt verfügbar. Aufrufe werden vom inneren .NET-Objekt über dessen IUnknown-Methoden zum steuernden IUnknown delegiert.
Aggregation ist ein wenig komplexer als die im nächsten Abschnitt beschriebene Kapselung. In der Regel wird sie zur Aktivierung des äußeren Objekts verwendet, um die Schnittstellenimplementierung eines anderen Objekts ohne Änderung verfügbar zu machen. Alle verwalteten Objekte unterstützen automatisch die Aggregation im Sinne von COM. Dabei wird das verwaltete Objekt als das innere Objekt verwendet. Um ein verwaltetes Objekt zusammenzusetzen, erstellt das nicht verwaltete äußere Objekt durch Aufruf von CoCreateInstance das verwaltete innere Objekt. Danach wird IUnknown des äußeren Objekts als OuterUnknown-Parameter übergeben. Wenn ein äußeres IUnknown während der Konstruktion einem verwalteten Objekt übergeben wird, wird die Schnittstelle durch das verwaltete Objekt zwischengespeichert und wie folgt verwendet:
Das äußere Objekt behält das nicht delegierende IUnknown des inneren IUnknown bei. Das nicht delegierende IUnknown verhält sich wie ein normales IUnknown, d. h., es wird erfolgreich aufgerufen, wenn das Objekt die Schnittstelle implementiert, andernfalls schlägt der Aufruf fehl. Das nicht delegierende IUnknown leitet den Aufruf nicht an das äußere Objekt weiter.
Wird eine nicht vom inneren Objekt unterstützte Schnittstelle abgefragt, delegiert das innere Objekt den Aufruf zur Schnittstelle IUnknown des äußeren Objekts.
Alle Aufrufe der QueryInterface-Methode, der AddRef-Methode und der Release-Methode des inneren Objekts werden an IUnknown des äußeren Objekts delegiert.
Durch diese drei Verhaltensweisen kann jedes beliebige verwaltete Objekt zusammengesetzt werden. Durch diese Art von Aggregationsbeziehung kann ein einzelnes COM-Objekt teils in verwaltetem (innerer Bereich) und teils in nicht verwaltetem Code (äußerer Bereich) implementiert sein.
Kapselung
Ein .NET-Objekt kann ein COM-Objekt enthalten, indem es seine Metadaten in eine .NET-Assembly importiert und dann ein Datenmember dieses Typs innerhalb einer anderen Klasse deklariert. Wie bei der normalen COM-Kapselung können Sie die Schnittstellen des COM-Objekts in Ihren eigenen Schnittstellenimplementierungen aufrufen. Das gekapselte Objekt wird aber nicht außerhalb der Klasse verfügbar gemacht. Kapselung ist einfacher als Aggregation. In der Regel wird Kapselung dann eingesetzt, wenn das äußere Objekt das Verhalten des inneren Objekts beeinflussen soll. Dazu erstellt das äußere Objekt einfach eine Instanz des inneren in seinem Konstruktor und delegiert gegebenenfalls Aufrufe zum inneren Objekt. Das äußere Objekt entscheidet, welche Aufrufe delegiert und welche direkt verarbeitet werden. Die Laufzeit stellt keine besonderen Anforderungen an Objekte zur Unterstützung der Kapselung.
Ein COM-Objekt kann auch ein .NET-Objekt enthalten. Das COM-Objekt verhält sich gegenüber Clients so, als wäre das enthaltene ein beliebiges COM-Objekt.
Siehe auch
Konzepte
Verfügbarmachen von COM-Komponenten für .NET Framework
Verfügbarmachen von .NET Framework-Komponenten in COM