Composants d’une extension VisualStudio.Extensibility

Une extension utilisant VisualStudio.Extensibility a généralement plusieurs composants qui interagissent ensemble et avec Visual Studio.

Instance d’extension

Les extensions doivent avoir une classe qui dérive de Extension. Pour obtenir un exemple d’implémentation, consultez MarkdownLinter.

Une instance de la Extension classe est le point de départ de l’exécution de l’extension. Cette instance contient les méthodes nécessaires pour que Visual Studio interroge les services fournis par l’extension. Il fournit également des méthodes virtuelles pour l’extension afin de fournir des ressources localisées et des services locaux appartenant à l’extension à partager entre les composants de l’extension.

La configuration de la Extension classe contient également les métadonnées de l’extension qui s’affiche dans la fenêtre Extensions de gestion de Visual Studio et, pour les extensions publiées, sur Visual Studio Marketplace.

[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"),
    };
    ...

Pour les développeurs d’extensions familiarisés avec les API existantes du KIT de développement logiciel (SDK) VS, le Metadata contenu est ExtensionConfiguration utilisé pour générer le .vsixmanifest fichier. En outre, la Extension classe est similaire à la AsyncPackage classe utilisée dans le modèle d’extensibilité du Kit de développement logiciel (SDK) VS.

Objet VisualStudioExtensibility

L’objet VisualStudioExtensibility agit comme point d’entrée pour les fonctionnalités d’extensibilité exposées par Visual Studio. Cette classe a différentes méthodes d’extension, propriétés permettant d’énumérer rapidement les fonctionnalités disponibles dans le Kit de développement logiciel (SDK) d’extensibilité. Consultez la documentation de l’API pour connaître les méthodes disponibles.

Parties d’extension

Pour les fonctionnalités où une extension contribue aux composants de Visual Studio, comme les commandes, les écouteurs d’éditeur, les extensions utilisent des classes attributées. Le processus de génération génère les métadonnées appropriées pour vous assurer que ces composants peuvent être découverts par Visual Studio.

Pour les fonctionnalités où une extension contribue aux composants de Visual Studio, tels que les commandes, les écouteurs d’éditeur, les fenêtres d’outils, etc., les extensions utilisent des classes marquées avec l’attribut VisualStudioContribution . Le processus de génération génère les métadonnées appropriées pour vous assurer que ces composants peuvent être découverts par Visual Studio.

Actuellement, le Kit de développement logiciel (SDK) prend en charge un ensemble limité de composants à apporter :

Les instances de ces classes sont créées dans le cadre de l’infrastructure d’extensibilité fournie par le Kit de développement logiciel (SDK) à l’aide d’une bibliothèque d’injection de dépendances, et les constructeurs peuvent être utilisés pour récupérer des instances de services fournis par le SDK ou par l’extension elle-même pour partager l’état entre les composants.

Durée de vie des parties d’extension

La durée de vie de chaque partie est gérée par le composant respectif qui charge ces composants dans le processus IDE Visual Studio.

  • Les gestionnaires de commandes sont initialisés lorsque le jeu de commandes correspondant est activé, ce qui peut se trouver pendant la première exécution de la commande. Une fois activés, les gestionnaires de commandes ne doivent être supprimés que lorsque l’IDE est arrêté.

  • De même, les écouteurs d’événements d’affichage de texte sont initialisés lorsque la première vue de texte correspondant au type de contenu spécifié est chargée dans l’IDE. Actuellement, ces écouteurs sont actifs jusqu’à ce que l’IDE soit arrêté, mais ce comportement peut changer à l’avenir.

En général, pour les extensions complexes, nous recommandons que les extensions fournissent des services locaux que les parties peuvent importer dans leur constructeur et utiliser ces services pour partager l’état entre les parties et entre les instances de la même partie. Cette pratique garantit que l’état de l’extension n’est pas affecté par les modifications de durée de vie des parties d’extension.

Services fournis par le Kit de développement logiciel (SDK) pour injection

Les services suivants sont fournis par le Kit de développement logiciel (SDK) qui peut être utilisé dans le constructeur pour n’importe quelle partie d’extension :

  • VisualStudioExtensibility: chaque composant d’extension peut injecter une instance d’interaction VisualStudioExtensibility avec l’IDE Visual Studio.

  • Extension: les parties peuvent injecter Microsoft.VisualStudio.Extensibility.Extension le type ou les extensions de leur propre type héritent de celui-ci vers les parties d’extension.

  • TraceSource: une instance source de trace est créée à la demande pour chaque extension qui peut être utilisée pour enregistrer les informations de diagnostic. Ces instances sont inscrites auprès du fournisseur de diagnostics Visual Studio qui peut être utilisé pour fusionner des journaux à partir de plusieurs services et utiliser des outils futurs pour accéder à la journalisation en temps réel. Voir Journalisation.

  • Services locaux : tous les services locaux fournis par l’extension elle-même seront également disponibles pour l’injection de dépendances.

  • MefInjection<TService> et AsyncServiceProviderInjection<TService, TInterface>: les extensions in-proc peuvent injecter des services sdk Visual Studio qui seraient traditionnellement consommés via MEF ou AsyncServiceProvider.

Services d’extension local

Dans certains scénarios, une extension peut souhaiter partager l’état entre différents composants, tels qu’un gestionnaire de commandes et un écouteur de modification d’affichage de texte, comme illustré dans l’exemple MarkdownLinter . Ces services peuvent être ajoutés à la collection de services in-process en substituant Extension.InitializeServices la méthode et à mesure que des instances de parties d’extension sont créées, les services sont injectés en fonction des arguments du constructeur.

Il existe trois options pour ajouter un service :

  • AddTransient: une nouvelle instance du service est créée pour chaque partie qui l’ingère.
  • AddScoped: une nouvelle instance du service est créée dans une certaine étendue. Dans le contexte de l’extensibilité de Visual Studio, l’étendue fait référence à une seule partie d’extension.
  • AddSingleton: il existe une instance partagée unique de service créée lors de la première ingestion.

En raison de la durée de vie de l’objet VisualStudioExtensibility lié à l’étendue d’une seule partie d’extension, tout service local qui l’ingère doit être un service délimité ou temporaire. La tentative de création d’un service singleton qui injecte VisualStudioExtensibility entraîne une défaillance.

Pour obtenir un exemple de l’utilisation des services locaux, consultez l’extension MarkdownLinter.

Contexte client

Étant donné que toutes les extensions du nouveau Kit de développement logiciel (SDK) sont hors processus, nous introduisons le concept de contexte client pour différentes parties d’extension afin de représenter l’état de l’IDE au moment où l’événement ou la méthode est appelé. Ce contexte est représenté par l’instance IClientContext du Kit de développement logiciel (SDK) et passe à différentes opérations telles que des gestionnaires d’exécution de commandes. Le Kit de développement logiciel (SDK) fournit des méthodes d’extension sur IClientContext qui peuvent être utilisées pour récupérer des objets à partir du contexte. Par exemple, les extensions peuvent obtenir l’affichage de texte actif ou l’URI des éléments sélectionnés au moment de l’exécution de la commande à l’aide de l’instance IClientContext .

Certains composants tels que les commandes vous permettent également de déclarer les contextes qui les intéressent. Cela permet d’optimiser la quantité de données transférées dans chaque exécution à distance, car le contexte client peut être volumineux à l’avenir. Dans la préversion initiale, il n’existe que deux contextes disponibles et ShellEditorles deux sont inclus par défaut lors de la déclaration d’une commande à l’aide CommandAttributede .