Komponenten einer VisualStudio.Extensibility-Erweiterung

Eine Erweiterung mit VisualStudio.Extensibility verfügt in der Regel über mehrere Komponenten, die zusammen und auch mit Visual Studio interagieren.

Erweiterungsinstanz

Erweiterungen müssen über eine Klasse verfügen, die von Extension. Eine Beispielimplementierung finden Sie unter MarkdownLinter.

Eine Instanz der Extension Klasse ist der Ausgangspunkt für die Ausführung der Erweiterung. Diese Instanz enthält die erforderlichen Methoden für Visual Studio zum Abfragen von Diensten, die von der Erweiterung bereitgestellt werden. Außerdem werden virtuelle Methoden für die Erweiterung bereitgestellt, um lokalisierte Ressourcen und lokale Dienste bereitzustellen, die zwischen den Komponenten der Erweiterung gemeinsam genutzt werden.

Die Konfiguration für die Extension Klasse enthält auch die Metadaten für die Erweiterung, die im Fenster "Erweiterungen verwalten" von Visual Studio und für veröffentlichte Erweiterungen auf dem Visual Studio Marketplace angezeigt wird.

[VisualStudioContribution]
public class MarkdownLinterExtension : Extension
{
    /// <inheritdoc/>
    public override ExtensionConfiguration ExtensionConfiguration => new()
    {
        Metadata = new(
                id: "MarkdownLinter.0cf26ba2-edd5-4419-8646-a55d0a83f7d8",
                version: this.ExtensionAssemblyVersion,
                publisherName: "Microsoft",
                displayName: "Markdown Linter Sample Extension",
                description: "Sample markdown linter extension"),
    };
    ...

Für Erweiterungsentwickler, die mit den vorhandenen VS SDK-APIs vertraut sind, wird die Metadata enthaltene ExtensionConfiguration Datei verwendet, um die .vsixmanifest Datei zu generieren. Außerdem ähnelt die Extension Klasse der AsyncPackage Klasse, die im VS SDK-Erweiterbarkeitsmodell verwendet wird.

VisualStudioExtensibility-Objekt

Das Objekt VisualStudioExtensibility fungiert als Einstiegspunkt für Erweiterbarkeitsfeatures, die von Visual Studio verfügbar gemacht werden. Diese Klasse verfügt über verschiedene Erweiterungsmethoden, Eigenschaften zum schnellen Aufzählen der verfügbaren Features im Erweiterbarkeits-SDK. Die verfügbaren Methoden finden Sie in der API-Dokumentation.

Erweiterungsteile

Für Features, bei denen eine Erweiterung Komponenten zu Visual Studio beiträgt, z. B. Befehle, Editorlistener, verwenden Erweiterungen Attributklassen. Der Buildprozess generiert die richtigen Metadaten, um sicherzustellen, dass diese Komponenten von Visual Studio ermittelt werden können.

Für Features, bei denen eine Erweiterung Komponenten zu Visual Studio beiträgt, z. B. Befehle, Editorlistener, Toolfenster usw., verwenden Erweiterungen Klassen, die mit dem VisualStudioContribution Attribut gekennzeichnet sind. Der Buildprozess generiert die richtigen Metadaten, um sicherzustellen, dass diese Komponenten von Visual Studio ermittelt werden können.

Derzeit unterstützt das SDK eine begrenzte Anzahl von Komponenten, die beigetragen werden sollen:

Instanzen für diese Klassen werden als Teil des Erweiterbarkeitsframeworks erstellt, das vom SDK mithilfe einer Abhängigkeitseinfügungsbibliothek bereitgestellt wird, und Konstruktoren können verwendet werden, um Instanzen von Diensten abzurufen, die vom SDK oder von der Erweiterung bereitgestellt werden, um den Zustand für komponentenübergreifend freizugeben.

Lebensdauer von Erweiterungsteilen

Die Lebensdauer der einzelnen Teile wird von der jeweiligen Komponente verwaltet, die diese Teile innerhalb des Visual Studio-IDE-Prozesses lädt.

  • Befehlshandler werden initialisiert, wenn der entsprechende Befehlssatz aktiviert wird, was während der ersten Ausführung des Befehls erfolgen kann. Nach der Aktivierung sollten Befehlshandler nur verworfen werden, wenn die IDE heruntergefahren wird.

  • Ebenso werden Ereignislistener für die Textansicht initialisiert, wenn die erste Textansicht mit dem angegebenen Inhaltstyp in der IDE geladen wird. Derzeit sind solche Listener aktiv, bis die IDE heruntergefahren wird, aber dieses Verhalten kann sich in Zukunft ändern.

Im Allgemeinen wird für komplexe Erweiterungen empfohlen, dass Erweiterungen lokale Dienste bereitstellen, die Teile in ihrem Konstruktor importieren und diese Dienste zum Freigeben des Zustands für Teile und für instanzen desselben Teils verwenden können. Diese Vorgehensweise stellt sicher, dass der Erweiterungszustand nicht von Änderungen der Lebensdauer von Erweiterungsteilen beeinflusst wird.

Vom SDK bereitgestellte Dienste für die Einfügung

Die folgenden Dienste werden vom SDK bereitgestellt, die für jeden Erweiterungsteil im Konstruktor verwendet werden können:

  • VisualStudioExtensibility: Jeder Erweiterungsteil kann eine Instanz der VisualStudioExtensibility Interaktion mit Visual Studio IDE einfügen.

  • Extension: Teile können Typ einfügen Microsoft.VisualStudio.Extensibility.Extension oder den eigenen Typ, der von ihr an Erweiterungsteile erbt.

  • TraceSource: Eine Ablaufverfolgungsquellinstanz wird bei Bedarf für jede Erweiterung erstellt, die zum Aufzeichnen von Diagnoseinformationen verwendet werden kann. Diese Instanzen werden bei Visual Studio Diagnose-Anbieter registriert, der zum Zusammenführen von Protokollen aus mehreren Diensten verwendet werden kann und zukünftige Tools für den Zugriff auf die Echtzeitprotokollierung verwendet werden kann. Siehe Protokollierung.

  • Lokale Dienste: Alle lokalen Dienste, die von der Erweiterung selbst bereitgestellt werden, stehen auch für die Abhängigkeitsinjektion zur Verfügung.

  • MefInjection<TService>und AsyncServiceProviderInjection<TService, TInterface>: In-proc-Erweiterungen können Visual Studio SDK-Dienste einfügen, die traditionell über MEF oder den AsyncServiceProvider genutzt werden.

Lokale Erweiterungsdienste

In bestimmten Szenarien möchte eine Erweiterung möglicherweise den Zustand zwischen verschiedenen Komponenten teilen, z. B. einem Befehlshandler und einem Textansichtsänderungslistener, wie im MarkdownLinter Beispiel zu sehen ist. Diese Dienste können der In-Process-Dienstauflistung durch Außerkraftsetzungsmethode Extension.InitializeServices hinzugefügt werden, und wenn Instanzen von Erweiterungsteilen erstellt werden, werden die Dienste basierend auf den Konstruktorargumenten eingefügt.

Es gibt drei Optionen zum Hinzufügen eines Diensts:

  • AddTransient: Für jeden Teil, der ihn einnimmt, wird eine neue Instanz des Diensts erstellt.
  • AddScoped: Eine neue Instanz des Diensts wird innerhalb eines bestimmten Bereichs erstellt. Im Kontext der Visual Studio-Erweiterbarkeit bezieht sich der Bereich auf einen einzelnen Erweiterungsteil.
  • AddSingleton: Es gibt eine einzelne freigegebene Dienstinstanz, die bei der ersten Aufnahme erstellt wird.

Aufgrund der Lebensdauer des VisualStudioExtensibility Objekts, das an den Bereich eines einzelnen Erweiterungsteils gebunden wird, muss jeder lokale Dienst, der die Komponente erfasst, ein bereichsbezogener oder vorübergehender Dienst sein. Wenn Sie versuchen, einen Singletondienst zu erstellen, der injiziert VisualStudioExtensibility wird, tritt ein Fehler auf.

Ein Beispiel für die Verwendung lokaler Dienste finden Sie unter MarkdownLinter-Erweiterung.

Kundenkontext

Da alle Erweiterungen im neuen SDK nicht mehr verarbeitet werden, wird das Konzept des Clientkontexts für verschiedene Erweiterungsteile eingeführt, um den Status der IDE zum Zeitpunkt des Aufrufs des Ereignisses oder der Methode darzustellen. Dieser Kontext wird durch die IClientContext Instanz im SDK dargestellt und an verschiedene Vorgänge wie Befehlsausführungshandler übergeben. Das SDK stellt Erweiterungsmethoden bereit, die IClientContext zum Abrufen von Objekten aus dem Kontext verwendet werden können. Beispielsweise können Erweiterungen die aktive Textansicht oder den URI für die ausgewählten Elemente zum Zeitpunkt der Befehlsausführung mithilfe der IClientContext Instanz abrufen.

Bei einigen Komponenten wie Befehlen können Sie auch deklarieren, an welchen Kontexten sie interessiert sind. Dies geschieht, um die In jeder Remoteausführung übertragene Datenmenge zu optimieren, da der Clientkontext in Zukunft groß werden kann. In der ersten Vorschau gibt es nur zwei verfügbare Kontexte, Shell und Editorbeide werden standardmäßig beim Deklarieren eines Befehls mit CommandAttributeeingeschlossen.