Inhaltsverzeichnis

Architektur

Das Add-in-Modell trennt sauber zwischen dem, was ein Add-in beschreibt, und dem, was es zur Laufzeit tut. Diese Trennung ist kein Selbstzweck. Sie erlaubt dem Host, die Oberfläche vollständig aufzubauen, bevor auch nur eine einzige Add-in-DLL geladen wird. Gleichzeitig definiert sie klare Verantwortlichkeiten: Der Host besitzt die Shell, das Add-in liefert Inhalt.

Zurück zur Übersicht.

Die zwei Ebenen

Ebene 1: Add-in-Metadaten

Die erste Ebene beschreibt das Add-in statisch. Alles, was der Host wissen muss, steht in einer einzigen JSON-Datei, dem Manifest. Dieses Manifest enthält:

Ebene 2: Add-in-Runtime

Die zweite Ebene ist der lebendige Code. Sobald der Host entscheidet, ein Add-in zu aktivieren, durchläuft es einen definierten Lebenszyklus:

Der Host-Vertrag

Der Host bleibt Eigentümer von allem, was zur Shell gehört. Diese Trennung ist bewusst gewählt, weil sie verhindert, dass ein fehlerhaftes oder bösartiges Add-in die Anwendung destabilisiert.

Was der Host kontrolliert

Was das Add-in liefert

Was dieses Modell vermeidet

Einige Entwurfsentscheidungen sind bewusst anders als bei verbreiteten Plugin-Systemen. Diese Abgrenzungen sind wichtig, weil sie häufige Fehlerquellen eliminieren.

Shell vs. Add-in: Grenzziehung

Die Shell und die Add-ins haben klar getrennte Verantwortlichkeiten. Diese Grenzziehung ist kein Detail, sondern ein Architekturprinzip. Jede Verletzung führt zu Duplikation, erschwerter Wartung und falschen Abhängigkeiten.

Was die Shell bereitstellt

Die Shell liefert provider-agnostische Infrastruktur, die für jedes Add-in wiederverwendbar ist:

Was die Shell NICHT tut

Warum diese Trennung?

1. Keine Duplikation. Wenn die Shell SQL-Queries oder View-Frames enthält, die das Add-in ebenfalls implementiert, existiert dieselbe Logik an zwei Stellen. Änderungen müssen synchron erfolgen — das passiert in der Praxis nicht.

2. Unabhängige Release-Zyklen. Add-ins können unabhängig vom Host aktualisiert werden. Wenn die Shell domänenspezifischen Code enthält, erzwingt jede Änderung am Datenmodell einen Shell-Release.

3. Testbarkeit. Die Shell lässt sich ohne Datenbank testen. Add-ins lassen sich mit Mock-Providern testen. Vermischte Verantwortlichkeiten machen beides unmöglich.

4. Wiederverwendbarkeit. Der Connection Manager, die Provider-Factories und die UI-Container sind für jedes Add-in nutzbar — nicht nur für ein bestimmtes Fachmodul.

Phasen der Verarbeitung

Der Host verarbeitet Add-ins in vier Phasen, die strikt nacheinander ablaufen:

  1. Scan — Der Host durchsucht zwei Verzeichnisse nach plugin.json-Dateien: <exe>/plugins/ (Machine-Scope, vom Administrator verwaltet) und ~/.wvdsx/extensions/ (User-Scope, Roaming-Profile-kompatibel). Jedes gefundene Manifest wird geparst und validiert. Fehlende Pflichtfelder führen dazu, dass das Add-in übersprungen wird.
  2. Resolve — Der Host baut einen Abhängigkeitsgraphen auf. Add-ins können andere Add-ins als Abhängigkeit deklarieren oder Services konsumieren, die ein anderes Add-in bereitstellt. Der Graph wird topologisch sortiert (Kahn-Algorithmus), um die korrekte Aktivierungsreihenfolge zu bestimmen. Zirkuläre Abhängigkeiten werden erkannt und gemeldet.
  3. Contributions registrieren — Noch bevor eine einzige DLL geladen wird, registriert der Host alle statischen Contributions aus den Manifesten. Für jeden deklarierten Command wird ein Lazy-Stub angelegt — ein Platzhalter, der beim ersten Aufruf die Aktivierung des Add-ins auslöst. Menüpunkte, Toolbar-Buttons und Tastenkürzel werden ebenfalls sofort registriert. Die Oberfläche steht damit vollständig.
  4. Activate — Add-ins mit onStartup werden sofort aktiviert. Alle anderen warten, bis ihr Aktivierungsereignis eintritt, typischerweise der erste Aufruf eines ihrer Commands. Bei der Aktivierung werden die Lazy-Stubs entfernt und durch die echten Handler des Add-ins ersetzt.

Weiter zu Manifest oder zurück zur Übersicht.