Verträge, Ansichten und Adapter
In diesem Thema werden Ansichten und Adapter, die Segmente, die beiden Seiten der Add-In-Pipeline gemeinsam sind, sowie der Vertrag, der sowohl vom Host als auch vom Add-In verwendet wird, beschrieben. In der folgenden Abbildung sind die Segmente der Add-In-Pipeline dargestellt.
Add-In-Pipeline
Codebeispiele finden Sie unter Exemplarische Vorgehensweise: Aktivieren der Abwärtskompatibilität bei geändertem Host und Exemplarische Vorgehensweise: Übergeben von Auflistungen zwischen Hosts und Add-Ins.
Verträge
Der erste Schritt bei der Entwicklung der Kommunikationspipeline besteht darin, einen von der IContract-Schnittstelle abgeleiteten Vertrag zu definieren. Wenn der Host und das Add-In in separate Anwendungsdomänen geladen werden, besteht zwischen der Add-In-Seite der Pipeline und der Hostseite der Pipeline eine Isolationsbegrenzung. Ein Vertrag ist eine Schnittstelle ohne Versionsverwaltung, die das Protokoll zum Übermitteln von Typen über eine Isolationsbegrenzung hinweg definiert. Durch die Verwendung von Verträgen für die Kommunikation über eine Isolationsbegrenzung hinweg verhindert das Add-In-Modell, dass die Typimplementierungen von Host und Add-In die Begrenzung durchdringen und Versionsprobleme verursachen.
Objekte, die übergreifend über Anwendungsdomänen übermittelt werden müssen, sollten remotefähig sein. Weitere Informationen über remotefähige Objekte finden Sie unter Remotable and Nonremotable Objects.
Die ContractBase-Klasse stellt eine Standardimplementierung von IContract-Membern bereit. Die Vertragsschnittstelle kann diese Klasse auch erben.
Anforderungen an Verträge
Verträge müssen eine Reihe von Voraussetzungen erfüllen, um sicherzustellen, dass alle innerhalb der Verträge genannten Typen sicher sind, versioniert werden können und dass die Isolationsbegrenzung zwischen Hosts und Add-Ins für Typen durchlässig ist.
Verträge müssen von IContract erben und dürfen nur die folgenden Typen verwenden:
Andere Verträge, die von IContract abgeleitet sind.
Primitive Datentypen: Ganzzahlen und boolesche Typen.
Serialisierbare, in der Vertragsassembly definierte Typen.
Serialisierbare, in Mscorlib.dll definierte Typen, z. B. Int32 und DateTime.
Versiegelte, serialisierbare Referenztypen. Ein String-Objekt kann beispielsweise durch die Isolationsbegrenzung übergeben werden, da es sich um einen versiegelten, serialisierbaren Referenztyp handelt.
Enumerationen, die im Vertrag oder in Mscorlib.dll definiert sind.
AddInToken-Objekte.
Arrays der zuvor aufgelisteten Typen außer einem aus Verträgen bestehenden Array.
Verwenden Sie zum Übergeben von Objektauflistungen Typen, die die generische IList<T>-Schnittstelle implementieren, z. B. die List<T>-Auflistung und die ArrayList-Auflistung. Um diese Auflistungen über die Isolationsbegrenzung hinweg zu übergeben, konvertieren Sie sie vorübergehend in die IListContract<T>-Schnittstelle. Das Thema Exemplarische Vorgehensweise: Übergeben von Auflistungen zwischen Hosts und Add-Ins veranschaulicht, wie Auflistungen übergeben werden.
Um die Pipeline zu erstellen, muss der Vertrag, der das Add-In darstellt, mit dem AddInContractAttribute-Attribut gekennzeichnet werden.
Der nächste Schritt bei der Entwicklung der Pipeline besteht darin, die Ansichts- und Adaptersegmente für beide Seiten der Pipeline zu erstellen. Diese Segmente bieten der Hostanwendung und dem Add-In Ansichten der entsprechenden Objektmodelle und stellen die Adapter bereit, mit denen diese Ansichten in den Vertrag konvertiert werden und umgekehrt.
Ansichten
Die Add-In-Ansicht des Hosts und die Hostansicht des Add-Ins sind Assemblys mit Schnittstellen oder abstrakten Klassen, die die gegenseitigen Ansichten sowie die Ansichten der Typen darstellen, die zwischen diesen Ansichten ausgetauscht werden. Ansichten sind nicht von den Verträgen abhängig, die für die wechselseitige Kommunikation verwendet werden. Ansichten gewährleisten auch die Trennung der Implementierungen von Add-In und Host. Dies bietet die Möglichkeit, dass Adapter und Vertrag ohne Auswirkungen auf den Host oder das Add-In geändert werden können.
Zur Erstellung der Pipeline wird der Typ in der Add-In-Ansicht, den das Add-In implementiert oder erbt, durch das AddInBaseAttribute-Attribut gekennzeichnet und als Add-In-Basis bezeichnet. Die Hostansicht erfordert kein Attribut für die Erkennung, da die Hostansicht an die FindAddIns-Methoden übergeben wird.
Adapter
Die Add-In-seitigen und hostseitigen Adapter sind Assemblys mit Adapterklassen, die für die Konvertierung in Ansichten und Verträge und umgekehrt verwendet werden. Der Begriff "Seite" bezieht sich auf die Seite der Pipeline, auf der sich ein Adapter befindet. Abhängig von der Richtung des Aufrufs führt der Adapter entweder eine Konvertierung von einer Ansicht in einen Vertrag oder von einem Vertrag in eine Ansicht durch. Wenn Aufrufe in beide Richtungen vorhanden sind (d. h., der Host sendet einen Aufruf an das Add-In und das Add-In an den Host), befinden sich auf beiden Seiten der Pipeline zwei Adapter. Folglich gibt es zwei Typen von Adaptern:
Ansicht-zu-Vertrag-Adapter
Eine Klasse in einer Adapterassembly, die eine Ansicht in einen Vertrag konvertiert. Diese Klasse implementiert den Vertrag, indem sie einen Aufruf in die an den zugehörigen Konstruktor übergebene Ansicht ausführt, und wird als Vertrag über die Begrenzung hinweg gemarshallt. Diese Klasse muss ContractBase erben und den Vertrag implementieren.
Vertrag-zu-Ansicht-Adapter
Eine Klasse in der Adapterassembly, die einen Vertrag in eine Ansicht konvertiert. Diese Klasse implementiert oder erbt das von ihr konvertierte Ansichtssegment, je nachdem, ob es sich bei der Ansicht um eine Schnittstelle oder einen abstrakten Basistyp handelt. Des Weiteren implementiert die Klasse die Member der Ansicht, indem sie den Vertrag aufruft, der an den Konstruktor des Adapters übergeben wird.
Um die Pipeline zu erstellen, müssen die Add-In-seitige Adapterklasse durch Zuweisen des AddInAdapterAttribute-Attributs und die hostseitige Adapterklasse durch Zuweisen des HostAdapterAttribute-Attributs gekennzeichnet werden.
Adapter müssen nicht öffentlich sein.