Creare un'estensione semplice
In Creare la prima estensione si è appreso come usare il modello di progetto VisualStudio.Extensibility per creare un progetto di estensione e come compilarlo ed eseguirne il debug nell'istanza sperimentale di Visual Studio.
In questa esercitazione si apprenderà come creare un'estensione con un semplice comando che esegue operazioni nell'editor di Visual Studio. In questo caso, inserisce un GUID appena generato. Si vedrà anche come indicare a Visual Studio i tipi di file per cui è abilitata l'estensione GUID e come visualizzare il nuovo comando come barra degli strumenti o voce di menu.
L'esempio completo per questa esercitazione è disponibile qui.
L'esercitazione contiene i passaggi seguenti:
Configurare il comando
In questo passaggio verranno fornite informazioni sulle opzioni per la configurazione e l'inserimento del comando. Lo scopo dell'hosting del comando consiste nell'esporlo all'utente in qualche modo, ad esempio l'aggiunta di una voce di menu o un pulsante della barra dei comandi.
Il modello di progetto o l'esempio creato nell'esercitazione Creare la prima estensione è costituito da un singolo file C# che include già una Command
classe. È possibile aggiornare questa funzionalità sul posto.
Rinominare il
Command1.cs
file inInsertGuidCommand.cs
, rinominare la classeInsertGuidCommand
, aggiornare laCommandConfiguration
proprietà .public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%") { Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu }, };
Placements
specifica dove deve essere visualizzato il comando nell'IDE. In questo caso, il comando viene inserito nel menu Estensioni, uno dei menu di primo livello in Visual Studio.L'argomento del
CommandConfiguration
costruttore è il nome visualizzato del comando, ovvero il testo del menu. Il nome visualizzato è racchiuso tra%
caratteri perché fa riferimento a una risorsa stringa da.vsextension/string-resources.json
per supportare la localizzazione.Aggiornare
.vsextension/string-resources.json
con il nome visualizzato diInsertGuidCommand
.{ "InsertGuidCommand.DisplayName": "Insert new guid" }
Aggiungere la proprietà
Icon
.public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%") { Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu }, Icon = new(ImageMoniker.KnownValues.OfficeWebExtension, IconSettings.IconAndText), };
È possibile specificare un'icona predefinita nota, in questo caso
OfficeWebExtension
o caricare immagini per l'icona come descritto in Aggiungere comandi di Visual Studio. Il secondo argomento è un'enumerazione che determina la modalità di visualizzazione del comando nelle barre degli strumenti (oltre alla relativa posizione in un menu). L'opzioneIconSettings.IconAndText
indica che mostra l'icona e il nome visualizzato l'uno accanto all'altro.Aggiungere la
VisibleWhen
proprietà , che specifica le condizioni che devono essere applicate per l'elemento da visualizzare all'utente.public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%") { Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu }, Icon = new(ImageMoniker.KnownValues.OfficeWebExtension, IconSettings.IconAndText), VisibleWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveEditorContentType, ".+"), };
Per altre informazioni, vedere Uso dei vincoli di attivazione basati su regole.
Creare il metodo di esecuzione
In questo passaggio si implementa il metodo del ExecuteCommandAsync
comando, che definisce cosa accade quando l'utente sceglie la voce di menu o preme l'elemento nella barra degli strumenti per il comando.
Copiare il codice seguente per implementare il metodo .
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
Requires.NotNull(context, nameof(context));
var newGuidString = Guid.NewGuid().ToString("N", CultureInfo.CurrentCulture);
using var textView = await context.GetActiveTextViewAsync(cancellationToken);
if (textView is null)
{
this.logger.TraceInformation("There was no active text view when command is executed.");
return;
}
await this.Extensibility.Editor().EditAsync(
batch =>
{
textView.Document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
},
cancellationToken);
}
La prima riga convalida gli argomenti, quindi viene creato un nuovo Guid
oggetto da usare in un secondo momento.
Viene quindi creato un ITextViewSnapshot
oggetto (l'oggetto textView
qui) chiamando il metodo GetActiveTextViewAsync
asincrono . Un token di annullamento viene passato per mantenere la possibilità di annullare la richiesta asincrona, ma questa parte non viene illustrata in questo esempio. Se non si ottiene correttamente una visualizzazione di testo, si scrive nel log e si termina senza eseguire altre operazioni.
A questo momento è possibile chiamare il metodo asincrono che invia una richiesta di modifica all'editor di Visual Studio. Il metodo desiderato è EditAsync
. Questo è un membro della EditorExtensibility
classe , che consente l'interazione con l'editor di Visual Studio in esecuzione nell'IDE. Il Command
tipo, da cui eredita la propria InsertGuidCommand
classe, ha un membro Extensibility
che fornisce l'accesso all'oggetto EditorExtensibility
, in modo da poter accedere alla EditorExtensibility
classe con una chiamata a this.Extensibility.Editor()
.
Il EditAsync
metodo accetta come Action<IEditBatch>
parametro . Questo parametro è denominato editorSource
,
La chiamata a EditAsync
usa un'espressione lambda. Per suddividere questo aspetto, è anche possibile scrivere tale chiamata come indicato di seguito:
await this.Extensibility.Editor().EditAsync(
batch =>
{
var editor = textView.Document.AsEditable(batch);
// specify the desired changes here:
editor.Replace(textView.Selection.Extent, newGuidString);
},
cancellationToken);
È possibile considerare questa chiamata come specificare il codice che si vuole eseguire nel processo dell'editor di Visual Studio. L'espressione lambda specifica ciò che si desidera modificare nell'editor. batch
è di tipo IEditBatch
, che implica che l'espressione lambda definita in questo caso apporta un piccolo set di modifiche che devono essere eseguite come unità, anziché essere interrotte da altre modifiche da parte dell'utente o del servizio di linguaggio. Se il codice viene eseguito troppo a lungo, ciò può causare la mancata risposta, quindi è importante mantenere limitate le modifiche all'interno di questa espressione lambda e comprendere tutto ciò che potrebbe causare ritardi.
Usando il AsEditable
metodo nel documento, si ottiene un oggetto editor temporaneo che è possibile utilizzare per specificare le modifiche desiderate. Si consideri tutto ciò che si trova nell'espressione lambda come una richiesta per l'esecuzione di Visual Studio anziché come effettivamente in esecuzione, perché come descritto in Usare l'estendibilità dell'editor di Visual Studio, esiste un particolare protocollo per gestire queste richieste di modifica asincrone dalle estensioni ed è possibile che le modifiche non vengano accettate, ad esempio se l'utente sta apportando modifiche contemporaneamente che creano un conflitto.
Il EditAsync
modello può essere usato per modificare il testo in generale specificando le modifiche dopo il commento "specificare le modifiche desiderate qui".