Freigeben über


Beiträge und Konfigurationen

Sie können Erweiterungen für Visual Studio verfügbar machen, indem Sie von bestimmten Basisklassen abgeleitet werden, und Sie können sie konfigurieren, indem Sie bestimmte Eigenschaften definieren und verschiedene Attribute verwenden.

Visual Studio-Beiträge

Der Zweck einer Visual Studio-Erweiterung besteht darin, neue Features zu Visual Studio beizutragen. Dies wird erreicht, indem eine von vielen Klassen wie Command, ToolWindowoder ExtensionPart erweitert und das attribut VisualStudioContribution angewendet wird.

In diesem Artikel wird auf die Command Parenting- Beispielerweiterung verwiesen, um die Konzepte des Beitragens und Konfigurierens von Erweiterungskomponenten zu erläutern.

Jede VisualStudio.Extensibility-Erweiterung muss mindestens eine Extension Klasse beitragen:

namespace CommandParentingSample;

[VisualStudioContribution]
public class CommandParentingSampleExtension : Extension
{
    /// <inheritdoc/>
    protected override void InitializeServices(IServiceCollection serviceCollection)
    {
        base.InitializeServices(serviceCollection);
    }
}

Die Extension-Klasse ist die erste instanziierte Klasse der Erweiterung und ermöglicht es Ihnen, dem IServiceCollection eigene Dienste hinzuzufügen, die zur Verwendung bei der Abhängigkeitsinjektiondienen.

Das Beispiel Command Parenting trägt eine weitere Klasse, eine Command, zu Visual Studio bei.

[VisualStudioContribution]
internal class SampleCommand : Command
{
    public SampleCommand()
    {
    }
    ...

Wenn Sie eine Basisklasse erweitern, die vom VisualStudio.Extensibility SDK bereitgestellt wird, können Sie wissen, ob Sie das attribut VisualStudioContribution verwenden sollen, indem Sie überprüfen, ob die Basisklasse IVisualStudioContributionClass implementiert (sowohl Extension als auch Command).

Visual Studio-Beitragsklassen sind faul instanziierte Singletons: Es wird nur eine Instanz erstellt, und die Erstellung wird verzögert, bis Visual Studio damit interagieren muss (z. B. wenn ein Command zuerst vom Benutzer aufgerufen wird).

Mit der VisualStudio.Extensibility-Infrastruktur können Sie auch Dienste über die Abhängigkeitseinfügung als Konstruktorparameter von Visual Studio-Beitragsklassen empfangen (siehe Dependency Injection in VisualStudio.Extensibility Extensions), einschließlich aller Dienste, die Sie dem IServiceCollection in der InitializeServices-Methode der Extension Klasse hinzugefügt haben.

Visual Studio erfordert häufig einen eindeutigen Bezeichner, der Beiträgen zugeordnet werden muss. In den meisten Fällen verwendet die VisualStudio.Extensibility-Infrastruktur den vollständigen Namen der Visual Studio-Beitragsklasse als Beitragsbezeichner. Der Bezeichner der obigen Extension Klasse wäre z. B. CommandParentingSample.CommandParentingSampleExtension. Möglicherweise sollten Sie sorgfältig den Typnamen und den Namespace Ihrer Visual Studio-Beitragsklassen auswählen, da sie in Visual Studio-Protokollen und Fehlermeldungen angezeigt werden können.

Konfigurieren von Visual Studio-Beiträgen

Für die meisten Visual Studio-Beitragsklassen ist eine Konfiguration erforderlich oder zulässig. Beispielsweise erfordert die Command abstrakte Klasse die Implementierung einer CommandConfiguration Eigenschaft, die mindestens den Anzeigenamen des Befehls und optional andere Eigenschaften wie die Platzierung angibt.

[VisualStudioContribution]
internal class SampleCommand : Command
{
    /// <inheritdoc />
    public override CommandConfiguration CommandConfiguration => new("%CommandParentingSample.SampleCommand.DisplayName%")
    {
        Placements = new[]
        {
            // File in project context menu
            CommandPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id: 1072, priority: 0),

            // Project context menu
            CommandPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id:  1026, priority: 0),

            // Solution context menu
            CommandPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id:  1043, priority: 0),
        },
    };
    ...

CommandConfiguration ist eine Kompilierungszeitkonstante, was bedeutet, dass der Wert ausgewertet wird, wenn die Erweiterung erstellt wird und sie im Erweiterungsmanifest enthalten ist (extension.json). Visual Studio kann das Erweiterungsmanifest lesen, ohne die Erweiterung selbst zu laden, was eine bessere Leistung ermöglicht.

Kompilierungszeitkonstanten unterliegen zusätzlichen Einschränkungen im Vergleich zu normalen Eigenschaften, z. B. müssen sie schreibgeschützt sein, und ihr Initialisierungscode darf keine Verweise auf nicht statische Member oder imperative Codeblöcke mit mehreren Anweisungen enthalten. Diese Einschränkungen werden von den VisualStudio.Extensibility-Buildtools erzwungen und führen zu Fehlermeldungen wie den folgenden:

Beim Auswerten der Kompilierungszeit-Konstante SampleCommand.CommandConfiguration ist ein Problem aufgetreten. Verweise auf benutzerdefinierte, nicht statische Member werden beim Auswerten von Konstantenwerten für die Kompilierungszeit nicht unterstützt.

Allgemein sollte die Erweiterung nicht auf Konfigurationseigenschaften der Kompilierungszeitkonstante zur Laufzeit verweisen.

Sie können problemlos Konfigurationseigenschaften der Kompilierungszeitkonstante identifizieren, da ihre Definition das Attribut CompileTimeEvaluation aufweist.

public abstract class Command : ExecutableCommandHandler, IVisualStudioContributionClass
{
    ...
    /// <summary>
    /// Gets the configuration for this command. The value of this property is evaluated at compile time
    /// when building the Visual Studio extension.
    /// </summary>
    [CompileTimeEvaluation]
    public abstract CommandConfiguration CommandConfiguration { get; }
    ...

In seltenen Fällen können Konfigurationseigenschaften optional sein. In bestimmten Fällen müssen Sie möglicherweise mehrere Konfigurationseigenschaften für dieselbe Klasse implementieren. Dies ist üblich, wenn sie ExtensionPart erweitern und mehrere Schnittstellen implementieren, die jeweils eine eigene Konfigurationseigenschaft erfordern.

Eigenständige Konfigurationseigenschaften

Wie oben beschrieben, definieren Visual Studio-Beitragsklassen eine Singleton-Klasse, die in der Regel eine oder mehrere Konfigurationseigenschaften der Kompilierungszeitkonstante verfügbar macht. Die Konfigurationseigenschaftenwerte werden als Erweiterungsmetadaten gespeichert.

Einige Erweiterungsfeatures erfordern, dass Sie Erweiterungsmetadaten angeben, die nicht an eine Klasse gebunden sind, und sie ist entweder eigenständig sinnvoll oder soll von anderen Konfigurationen referenziert werden. Einige Beispiele sind Menü-, Symbolleisten- und Dokumenttypdefinitionen. Dies wird durch Anwenden des VisualStudioContribution-Attributs auf eine statische Readonly-Konfigurationseigenschaft erreicht.

Visual Studio-Beitragseigenschaften können in einer beliebigen Klasse platziert werden.

Das beispiel Command Parenting definiert eine Symbolleiste, indem eine statische Eigenschaft vom Typ ToolbarConfiguration deklariert und als VisualStudioContributionmarkiert wird.

namespace CommandParentingSample;

internal static class ExtensionCommandConfiguration
{
    [VisualStudioContribution]
    public static ToolbarConfiguration ToolBar => new("%CommandParentingSample.ToolBar.DisplayName%")
    {
        Children = new[]
        {
            ToolbarChild.Command<SampleCommand>(),
        },
    };
}

Visual Studio-Beitragseigenschaften sind auch Kompilierungszeitkonstanten und unterliegen den gleichen Einschränkungen, die zuvor erläutert wurden.

Eine Visual Studio-Beitragseigenschaft kann auch auf eine andere Konfigurationseigenschaft verweisen. Zum Beispiel:

public static class MenuConfigurations
{
    [VisualStudioContribution]
    public static CommandGroupConfiguration MyCommandGroup => new(GroupPlacement.KnownPlacements.ExtensionsMenu)
    {
        Children = new GroupChild[]
        {
            GroupChild.Menu(MyMenu),
        },
    };

    [VisualStudioContribution]
    public static MenuConfiguration MyMenu => new("%MyMenu.DisplayName%")
    {
        Children = new[]
        {
            MenuChild.Command<MyCommand>(),
        },
    };
    ...

Typen, die zum Definieren von Visual Studio-Beitragseigenschaften verwendet werden sollen, implementieren die IVisualStudioContributionProperty Schnittstelle und werden mit dem attribut CompileTimeEvaluation gekennzeichnet, um zu dokumentieren, dass ihre Werte beim Erstellen der Erweiterung ausgewertet werden.

[CompileTimeEvaluation]
public sealed class DocumentTypeConfiguration : IVisualStudioContributionProperty ...

Der Leitfaden, nicht auf Konfigurationseigenschaften derKompilierungszeitkonstante während der Laufzeit zu verweisen, gilt auch für Visual Studio-Beitragseigenschaften.

Falls für eine Visual-Studio-Beitragseigenschaft ein eindeutiger Bezeichner erforderlich ist, wird der vollständige Name (der den vollständigen Namen und den Eigenschaftsnamen des Typs enthält) von der VisualStudio.Extensibility-Infrastruktur als Bezeichner verwendet. Der eindeutige Bezeichner der hier beschriebenen Symbolleistenkonfiguration wäre z. B. CommandParentingSample.ExtensionCommandConfiguration.ToolbarConfiguration.