Partager via


Contributions et configurations

Vous pouvez exposer des composants d’extensions à Visual Studio en dérivant de certaines classes de base, et vous pouvez les configurer en définissant certaines propriétés et en utilisant différents attributs.

Visual Studio Contributions

L’objectif d’une extension Visual Studio est de contribuer à de nouvelles fonctionnalités à Visual Studio. Cela est obtenu en étendant l’une des nombreuses classes telles que Command, ToolWindowou ExtensionPart en appliquant l’attribut VisualStudioContribution .

Cet article fait référence à l’exemple d’extension Parenting de commandes pour expliquer les concepts de contribution et de configuration des composants d’extension.

Chaque extension VisualStudio.Extensibility doit contribuer au moins à une Extension classe :

namespace CommandParentingSample;

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

La Extension classe est la première classe instanciée de l’extension et vous permet d’ajouter vos propres services à l’injection IServiceCollection de dépendances.

L’exemple De parentage de commandes contribue à une autre classe, un Command, à Visual Studio :

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

Lors de l’extension d’une classe de base fournie par le Kit de développement logiciel (SDK) VisualStudio.Extensibility, vous pouvez savoir si vous êtes censé utiliser l’attribut VisualStudioContribution en case activée si la classe de base implémente IVisualStudioContributionClass (à la fois Extension et Command effectue).

Les classes de contribution Visual Studio sont des singletons instanciés de manière différée : une seule instance est créée et sa création est retardée jusqu’à ce que Visual Studio ait besoin d’interagir avec elle (par exemple, lorsqu’un Command utilisateur appelle pour la première fois).

L’infrastructure VisualStudio.Extensibility vous permet également de recevoir des services via l’injection de dépendances en tant que paramètres de constructeur des classes de contribution Visual Studio (voir Services fournis par le Kit de développement logiciel (SDK) pour injection), y compris tout service que vous avez ajouté à la IServiceCollection méthode de InitializeServices la Extension classe.

Visual Studio nécessite souvent un identificateur unique pour être associé à des contributions. Dans la plupart des cas, l’infrastructure VisualStudio.Extensibility utilise le nom complet de la classe de contribution Visual Studio comme identificateur de contribution. Par exemple, l’identificateur de la Extension classe ci-dessus serait CommandParentingSample.CommandParentingSampleExtension. Vous pouvez choisir soigneusement le nom de type et l’espace de noms de vos classes de contribution Visual Studio, car elles peuvent apparaître dans les journaux visual Studio et les messages d’erreur.

Configuration des contributions Visual Studio

La plupart des classes de contribution Visual Studio nécessitent ou autorisent la configuration. Par exemple, la Command classe abstraite nécessite l’implémentation d’une CommandConfiguration propriété spécifiant au moins le nom d’affichage de la commande et, éventuellement, d’autres propriétés telles que son placement.

[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 est une constante au moment de la compilation, ce qui signifie que sa valeur est évaluée lorsque l’extension est générée et qu’elle est incluse dans le manifeste d’extension (extension.json). Visual Studio peut lire le manifeste d’extension sans charger l’extension elle-même, ce qui permet de meilleures performances.

Les constantes au moment de la compilation sont soumises à des limitations supplémentaires par rapport aux propriétés normales , par exemple, elles doivent être lues en lecture seule et leur code d’initialisation ne peut pas inclure de références à des membres non statiques ou à des blocs de code impératifs à plusieurs instructions. Ces restrictions sont appliquées par les outils de génération VisualStudio.Extensibility et entraînent des messages d’erreur comme suit :

Un problème a été rencontré lors de l’évaluation de la constante sampleCommand.CommandConfiguration au moment de la compilation. Les références aux membres non statiques définis par l’utilisateur ne sont pas prises en charge lors de l’évaluation des valeurs constantes au moment de la compilation.

En règle générale, l’extension ne doit pas référencer les propriétés de configuration constante au moment de l’exécution.

Vous pouvez facilement identifier les propriétés de configuration constante au moment de la compilation, car leur définition a l’attribut CompileTimeEvaluation .

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; }
    ...

Dans de rares cas, les propriétés de configuration peuvent être facultatives. Dans certains cas, vous devrez peut-être implémenter plusieurs propriétés de configuration sur la même classe. Cela est courant lors de l’extension ExtensionPart et de l’implémentation de plusieurs interfaces, chacune nécessitant sa propre propriété de configuration.

Propriétés de configuration autonomes

Comme décrit ci-dessus, les classes de contribution Visual Studio définissent une classe singleton qui expose généralement une ou plusieurs propriétés de configuration constante au moment de la compilation. Les valeurs des propriétés de configuration sont enregistrées en tant que métadonnées d’extension.

Certaines fonctionnalités d’extensibilité vous obligent à spécifier des métadonnées d’extension qui ne sont liées à aucune classe et qu’elles sont significatives par elles-mêmes ou qu’elles sont destinées à être référencées par d’autres configurations. Voici quelques exemples de définitions de menu, de barre d’outils et de type de document. Pour ce faire, appliquez l’attribut VisualStudioContribution à une propriété de configuration en lecture seule statique.

Les propriétés de contribution de Visual Studio peuvent être placées dans n’importe quelle classe.

L’exemple De parentage de commande définit une barre d’outils en déclarant une propriété statique de type ToolbarConfiguration et en la marquant comme VisualStudioContribution.

namespace CommandParentingSample;

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

Les propriétés de contribution de Visual Studio sont également des constantes au moment de la compilation et sont soumises aux mêmes limitations décrites précédemment.

Une propriété de contribution Visual Studio peut également référencer une autre propriété de configuration. Par exemple :

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

Les types destinés à être utilisés pour définir des propriétés de contribution Visual Studio implémentent l’interface IVisualStudioContributionProperty et sont marqués avec l’attribut CompileTimeEvaluation pour documenter que leurs valeurs sont évaluées lorsque l’extension est générée.

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

Les instructions relatives à la non référencement des propriétés de configuration constante au moment de la compilation au moment de l’exécution s’appliquent également aux propriétés de contribution visual Studio.

Si un identificateur unique est requis pour une propriété de contribution Visual Studio, son nom complet (contenant le nom complet du type et le nom de propriété) est utilisé par l’infrastructure VisualStudio.Extensibility comme identificateur. Par exemple, l’identificateur unique de la configuration de la barre d’outils abordé ici serait CommandParentingSample.ExtensionCommandConfiguration.ToolbarConfiguration.