Crie uma extensão simples
Em Criar sua primeira extensão, você aprendeu a usar o modelo de projeto VisualStudio.Extensibility para criar um projeto de extensão e aprendeu como criá-lo e depurá-lo na instância experimental do Visual Studio.
Neste tutorial, você aprenderá a criar uma extensão com um comando simples que faz algo no editor do Visual Studio. Nesse caso, ele insere um GUID recém-gerado. Você também verá como informar ao Visual Studio para quais tipos de arquivo a extensão GUID está habilitada e como fazer com que o novo comando apareça como uma barra de ferramentas ou item de menu.
O exemplo completo para este tutorial pode ser encontrado aqui.
O tutorial contém as seguintes etapas:
Configurar o comando
Nesta etapa, você aprenderá sobre as opções para configurar e colocar o comando. O objetivo de hospedar o comando é expô-lo ao usuário de alguma forma, como adicionar um item de menu ou um botão da barra de comandos.
O modelo de projeto ou o exemplo criado no tutorial Criar sua primeira extensão consiste em um único arquivo C# que já inclui uma Command
classe. Você pode atualizar isso no lugar.
Renomeie o arquivo para , renomeie
Command1.cs
a classeInsertGuidCommand
, atualize aCommandConfiguration
propriedade.InsertGuidCommand.cs
public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%") { Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu }, };
Placements
especifica onde o comando deve aparecer no IDE. Nesse caso, o comando é colocado no menu Extensões, um dos menus de nível superior no Visual Studio.O argumento para o construtor é o nome de exibição do comando, que é o
CommandConfiguration
texto do menu. O nome de exibição é delimitado por%
caracteres porque faz referência a um recurso de cadeia de caracteres para.vsextension/string-resources.json
oferecer suporte à localização.Atualizar
.vsextension/string-resources.json
com o nome de exibição doInsertGuidCommand
.{ "InsertGuidCommand.DisplayName": "Insert new guid" }
Adicione a propriedade
Icon
.public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%") { Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu }, Icon = new(ImageMoniker.KnownValues.OfficeWebExtension, IconSettings.IconAndText), };
Você pode especificar um ícone interno conhecido, neste caso
OfficeWebExtension
, ou carregar imagens para o ícone, conforme descrito em Adicionar comandos do Visual Studio. O segundo argumento é uma enumeração que determina como o comando deve aparecer nas barras de ferramentas (além de seu lugar em um menu). A opçãoIconSettings.IconAndText
significa mostrar o ícone e o nome de exibição um ao lado do outro.Adicione a
VisibleWhen
propriedade, que especifica as condições que devem ser aplicadas para que o item apareça para o usuário.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, ".+"), };
Consulte Usando restrições de ativação baseadas em regras para obter mais informações.
Criar o método de execução
Nesta etapa, você implementa o método do ExecuteCommandAsync
comando, que define o que acontece quando o usuário escolhe o item de menu ou pressiona o item na barra de ferramentas do comando.
Copie o código a seguir para implementar o método.
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);
}
A primeira linha valida os argumentos e, em seguida, criamos um novo Guid
para usar mais tarde.
Em seguida, criamos um ITextViewSnapshot
(o objeto aqui) chamando o textView
método GetActiveTextViewAsync
assíncrono . Um token de cancelamento é passado para preservar a capacidade de cancelar a solicitação assíncrona, mas essa parte não é demonstrada neste exemplo. Se não obtivermos uma visualização de texto com sucesso, gravamos no log e encerramos sem fazer mais nada.
Agora estamos prontos para chamar o método assíncrono que envia uma solicitação de edição ao editor do Visual Studio. O método que queremos é EditAsync
. Esse é um membro da classe, que permite a EditorExtensibility
interação com o Editor do Visual Studio em execução no IDE. O Command
tipo, do qual sua própria InsertGuidCommand
classe herda, tem um membro Extensibility
que fornece acesso ao EditorExtensibility
objeto, para que possamos chegar à EditorExtensibility
classe com uma chamada para this.Extensibility.Editor()
.
O EditAsync
método usa um Action<IEditBatch>
como parâmetro. Esse parâmetro é chamado editorSource
de ,
A chamada para EditAsync
usa uma expressão lambda. Para detalhar um pouco isso, você também pode escrever essa chamada da seguinte maneira:
await this.Extensibility.Editor().EditAsync(
batch =>
{
var editor = textView.Document.AsEditable(batch);
// specify the desired changes here:
editor.Replace(textView.Selection.Extent, newGuidString);
},
cancellationToken);
Você pode pensar nessa chamada como especificando o código que você deseja que seja executado no processo do editor do Visual Studio. A expressão lambda especifica o que você deseja alterar no editor. O batch
é do tipo IEditBatch
, o que implica que a expressão lambda definida aqui faz um pequeno conjunto de alterações que devem ser realizadas como uma unidade, em vez de serem interrompidas por outras edições pelo usuário ou serviço de idioma. Se o código for executado por muito tempo, isso pode levar à falta de resposta, por isso é importante manter as alterações dentro dessa expressão lambda limitadas e entender qualquer coisa que possa levar a atrasos.
Usando o AsEditable
método no documento, você obtém um objeto de editor temporário que pode ser usado para especificar as alterações desejadas. Pense em tudo na expressão lambda como uma solicitação para o Visual Studio executar em vez de como realmente em execução, porque, conforme descrito em Usar extensibilidade do editor do Visual Studio, há um protocolo específico para lidar com essas solicitações de edição assíncronas de extensões, e há uma possibilidade de as alterações não serem aceitas, como se o usuário estiver fazendo alterações ao mesmo tempo que criem um conflito.
O EditAsync
padrão pode ser usado para modificar o texto em geral, especificando suas modificações após o comentário "especifique suas alterações desejadas aqui".