Tworzenie prostego rozszerzenia

W artykule Tworzenie pierwszego rozszerzenia przedstawiono sposób tworzenia projektu VisualStudio.Extensibility przy użyciu szablonu projektu VisualStudio.Extensibility oraz dowiedz się, jak go skompilować i debugować w eksperymentalnym wystąpieniu programu Visual Studio.

Z tego samouczka dowiesz się, jak utworzyć rozszerzenie za pomocą prostego polecenia, które wykonuje coś w edytorze programu Visual Studio. W tym przypadku wstawia nowo wygenerowany identyfikator GUID. Zobaczysz również, jak poinformować program Visual Studio o typach plików, dla których włączono rozszerzenie IDENTYFIKATORa GUID, oraz jak utworzyć nowe polecenie jako pasek narzędzi lub element menu.

Ukończony przykład dla tego samouczka można znaleźć tutaj.

Samouczek zawiera następujące kroki:

Konfigurowanie polecenia

W tym kroku poznasz opcje konfigurowania i umieszczania polecenia. Celem hostowania polecenia jest uwidocznienie go użytkownikowi w jakiś sposób, na przykład dodanie elementu menu lub przycisku paska poleceń.

Szablon projektu lub przykład utworzony w samouczku Tworzenie pierwszego rozszerzenia składa się z pojedynczego pliku języka C#, który zawiera już klasę Command . Możesz to zaktualizować.

  1. Zmień nazwę pliku na InsertGuidCommand.csCommand1.cs , zmień nazwę klasy InsertGuidCommand, zaktualizuj CommandConfiguration właściwość .

    public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%")
    {
        Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu },
    };
    

    Placements określa, gdzie polecenie powinno być wyświetlane w środowisku IDE. W takim przypadku polecenie zostanie umieszczone w menu Rozszerzenia, jednym z menu najwyższego poziomu w programie Visual Studio.

    Argumentem konstruktora CommandConfiguration jest nazwa wyświetlana polecenia, czyli tekst menu. Nazwa wyświetlana jest ujęta przez % znaki, ponieważ odwołuje się do zasobu ciągu z .vsextension/string-resources.json , aby obsługiwać lokalizację.

  2. Zaktualizuj .vsextension/string-resources.json element o nazwie wyświetlanej .InsertGuidCommand

    {
      "InsertGuidCommand.DisplayName": "Insert new guid"
    }
    
  3. Icon Dodaj właściwość .

    public override CommandConfiguration CommandConfiguration => new("%InsertGuidCommand.DisplayName%")
    {
        Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu },
        Icon = new(ImageMoniker.KnownValues.OfficeWebExtension, IconSettings.IconAndText),
    };
    

    W tym przypadku OfficeWebExtensionmożna określić znaną wbudowaną ikonę lub przekazać obrazy dla ikony zgodnie z opisem w temacie Dodawanie poleceń programu Visual Studio. Drugi argument to wyliczenie, które określa, jak polecenie powinno być wyświetlane na paskach narzędzi (oprócz jego miejsca w menu). Opcja IconSettings.IconAndText oznacza wyświetlenie ikony i nazwy wyświetlanej obok siebie.

  4. VisibleWhen Dodaj właściwość , która określa warunki, które muszą mieć zastosowanie do elementu, aby był wyświetlany użytkownikowi.

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

Aby uzyskać więcej informacji, zobacz używanie ograniczeń aktywacji opartych na regułach.

Tworzenie metody wykonywania

W tym kroku zaimplementujesz metodę polecenia ExecuteCommandAsync , która definiuje, co się stanie, gdy użytkownik wybierze element menu lub naciśnie element na pasku narzędzi polecenia.

Skopiuj następujący kod, aby zaimplementować metodę .

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

Pierwszy wiersz weryfikuje argumenty, a następnie tworzymy nowy Guid , który będzie używany później.

Następnie utworzymy ITextViewSnapshot obiekt ( textView obiekt tutaj), wywołując metodę GetActiveTextViewAsyncasynchroniczną . Token anulowania jest przekazywany w celu zachowania możliwości anulowania żądania asynchronicznego, ale ta część nie jest pokazana w tym przykładzie. Jeśli nie otrzymamy widoku tekstowego pomyślnie, zapisujemy w dzienniku i kończymy działanie bez wykonywania żadnych innych czynności.

Teraz możemy wywołać metodę asynchroniczną, która przesyła żądanie edycji do edytora programu Visual Studio. Metoda, której potrzebujemy, to EditAsync. Jest to element członkowski EditorExtensibility klasy, który umożliwia interakcję z uruchomionym edytorem programu Visual Studio w środowisku IDE. Command Typ, z którego dziedziczy Twoja klasaInsertGuidCommand, ma element członkowskiExtensibility, który zapewnia dostęp do EditorExtensibility obiektu, dzięki czemu możemy przejść do EditorExtensibility klasy za pomocą wywołania metody this.Extensibility.Editor().

Metoda EditAsync przyjmuje parametr Action<IEditBatch> jako parametr. Ten parametr nosi nazwę editorSource,

Wywołanie do EditAsync użycia wyrażenia lambda. Aby nieco to podzielić, możesz również napisać to wywołanie w następujący sposób:

await this.Extensibility.Editor().EditAsync(
    batch =>
    {
        var editor = textView.Document.AsEditable(batch);
        // specify the desired changes here:
        editor.Replace(textView.Selection.Extent, newGuidString);
    },
    cancellationToken);

To wywołanie można traktować jako określenie kodu, który chcesz uruchomić w procesie edytora programu Visual Studio. Wyrażenie lambda określa, co chcesz zmienić w edytorze. Jest batch typu IEditBatch, co oznacza, że wyrażenie lambda zdefiniowane w tym miejscu sprawia, że niewielki zestaw zmian, które powinny zostać wykonane jako jednostka, a nie przerywane przez inne zmiany przez użytkownika lub usługę językową. Jeśli kod jest wykonywany zbyt długo, może to prowadzić do braku odpowiedzi, dlatego ważne jest, aby zmiany w tym wyrażeniu lambda były ograniczone i zrozumiały wszystko, co może prowadzić do opóźnień.

AsEditable Za pomocą metody w dokumencie uzyskasz obiekt edytora tymczasowego, którego można użyć do określenia żądanych zmian. Pomyśl o wszystkim w wyrażeniu lambda jako żądaniu wykonania programu Visual Studio, a nie jako rzeczywistego wykonania, ponieważ zgodnie z opisem w rozszerzalności edytora programu Visual Studio istnieje określony protokół do obsługi tych asynchronicznych żądań edycji z rozszerzeń i istnieje możliwość, że zmiany nie są akceptowane, na przykład jeśli użytkownik wprowadza zmiany w tym samym czasie, co powoduje konflikt.

Wzorzec EditAsync może służyć do modyfikowania tekstu w ogóle, określając modyfikacje po komentarzu "określ żądane zmiany tutaj".