Composants d’une extension VisualStudio.Extensibility
Une extension utilisant VisualStudio.Extensibility comprend généralement plusieurs composants qui interagissent ensemble et également avec Visual Studio.
Instance d’extension
Les extensions doivent avoir une classe qui dérive de Extension
. Pour un exemple d’implémentation, veuillez consulter la section MarkdownLinter.
Une instance de la classe Extension
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. Elle fournit également des méthodes virtuelles pour que l’extension fournisse des ressources localisées et des services locaux appartenant à l’extension, à partager entre les composants de l’extension.
La configuration de la classe Extension
contient également les métadonnées de l’extension, qui sont affichées dans la fenêtre Gérer les extensions de Visual Studio, et pour les extensions publiées, sur le 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 VSSDK existantes, la classe Metadata
contenue dans ExtensionConfiguration
est utilisée pour générer le fichier .vsixmanifest
. De plus, la classe Extension
est similaire à la classe AsyncPackage
utilisée dans le modèle d’extensibilité VSSDK.
Objet VisualStudioExtensibility
L’objet VisualStudioExtensibility
agit comme le point d’entrée pour les fonctionnalités d’extensibilité exposées par Visual Studio. Cette classe possède diverses méthodes d’extension, des propriétés permettant de parcourir rapidement les fonctionnalités disponibles dans le SDK d’extensibilité. Veuillez consulter la documentation API pour les méthodes disponibles.
Parties d’extension
Pour les fonctionnalités où une extension contribue à des composants de Visual Studio, comme des commandes, des écouteurs d’éditeur, les extensions utiliseront des classes attribuées. Le processus de build générera les métadonnées correctes pour s’assurer que ces composants puissent être découverts par Visual Studio.
Pour les fonctionnalités où une extension contribue à des composants de Visual Studio, comme des commandes, des écouteurs d’éditeur, des fenêtres d’outils, etc., les extensions utilisent des classes marquées avec l’attribut VisualStudioContribution
. Le processus de build génère les métadonnées correctes pour s’assurer que ces composants puissent être découverts par Visual Studio.
Actuellement, le SDK prend en charge un ensemble limité de composants pouvant être contribués :
- Gestionnaires de commandes
- Fenêtres d’outil
- Écouteurs d’ouverture/fermeture d’affichage texte pour suivre la création et la fermeture d’un affichage texte.
- Écouteurs de changement d’affichage texte pour suivre les modifications apportées à un affichage texte ouvert.
- Fournisseurs de marge
- Visualiseurs du débogueur
Les instances de ces classes sont créées dans le cadre du framework d’extensibilité fourni par le 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 soit par le SDK soit 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 parties dans le processus de l’IDE Visual Studio.
Les gestionnaires de commandes sont initialisés lorsque l’ensemble de commandes correspondant est activé, ce qui peut se produire lors de 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 fermé.
De même, les écouteurs d’événements d’affichage texte sont initialisés lorsque le premier affichage texte correspondant au type de contenu spécifié est chargé dans l’IDE. Actuellement, ces écouteurs restent actifs jusqu’à la fermeture de l’IDE, 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 utilisent ces services pour partager l’état entre les parties et entre les instances d’une même partie. Cette pratique garantit que l’état de l’extension n’est pas affecté par les changements de durée de vie des parties d’extension.
Services fournis par le SDK pour l’injection
Les services suivants sont fournis par le SDK et peuvent être utilisés dans le constructeur pour toute partie de l’extension :
VisualStudioExtensibility
: Chaque partie de l’extension peut injecter une instance deVisualStudioExtensibility
pour interagir avec l’IDE Visual Studio.Extension
: Les parties peuvent injecter un typeMicrosoft.VisualStudio.Extensibility.Extension
ou leur propre type d’extensions hérité pour les parties d’extension.TraceSource
: Une instance de source de trace est créée à la demande pour chaque extension, et peut être utilisée pour enregistrer des informations de diagnostic. Ces instances sont enregistrées auprès du fournisseur de diagnostics de Visual Studio, qui peut être utilisé pour fusionner les journaux de plusieurs services et utiliser des outils futurs pour accéder à la journalisation en temps réel. Veuillez consulter la section 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>
etAsyncServiceProviderInjection<TService, TInterface>
: Les extensions in-process peuvent injecter des services Visual Studio SDK qui seraient traditionnellement consommés soit via MEF soit via le AsyncServiceProvider.
Services locaux d’extension
Dans certains scénarios, une extension peut vouloir partager un état entre différents composants, comme un gestionnaire de commandes et un écouteur de changement d’affichage texte, comme cela peut être vu dans l’exemple MarkdownLinter
. Ces services peuvent être ajoutés à la collection de services in-process en remplaçant la méthode Extension.InitializeServices
, et au fur et à mesure que les instances des 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é Visual Studio, l’étendue se réfère à une seule partie de l’extension.AddSingleton
: Il existe une instance partagée unique du service qui est créée lors de la première ingestion.
En raison de la durée de vie de l’objet VisualStudioExtensibility
étant liée à l’étendue d’une seule partie de l’extension, tout service local qui l’ingère doit être un service scoped ou transitoire. Tenter de créer un service singleton qui injecte VisualStudioExtensibility
entraînera un échec.
Pour un exemple d’utilisation des services locaux, veuillez consulter la section Extension MarkdownLinter.
Contexte client
Étant donné que toutes les extensions du nouveau SDK s’exécutent hors processus, nous introduisons le concept de contexte client pour diverses parties de l’extension afin de représenter l’état de l’IDE au moment où l’événement ou la méthode est invoqué. Ce contexte est représenté par l’instance IClientContext
dans le SDK et est passé à diverses opérations telles que les gestionnaires d’exécution de commande. Le SDK fournit des méthodes d’extension sur IClientContext
qui peuvent être utilisées pour récupérer des objets du contexte. Par exemple, les extensions peuvent obtenir l’affichage texte actif ou l’URI des éléments sélectionnés au moment de l’exécution de la commande en utilisant l’instance IClientContext
.
Certains composants, comme les commandes, vous permettent également de déclarer les contextes qui les intéressent. Cela est fait pour optimiser la quantité de données transférées lors de chaque exécution à distance, car le contexte client peut devenir volumineux à l’avenir. Dans la version préliminaire initiale, il n’y a que deux contextes disponibles, Shell
et Editor
, et les deux sont inclus par défaut lors de la déclaration d’une commande à l’aide de CommandAttribute
.