建立簡單的延伸模組

建立您的第一個延伸模組中,您已瞭解如何使用VisualStudio.Extensibility項目範本來建立延伸模組專案,並瞭解如何在Visual Studio的實驗實例中建置和偵錯它。

在本教學課程中,您將瞭解如何使用在Visual Studio編輯器執行某些動作的簡單命令來建立延伸模組。 在此情況下,它會插入新產生的 GUID。 您也會瞭解如何告訴 Visual Studio 已啟用 GUID 延伸模組的檔案類型,以及如何讓新命令顯示為工具列或功能表項。

您可以在這裡找到本教學課程的已完成範例。

本教學課程包含下列步驟:

設定命令

在此步驟中,您將了解設定和放置命令的選項。 裝載命令的目的是要以某種方式向用戶公開命令,例如新增功能表項或命令行按鈕。

您在建立第一個延伸模組教學課程中建立的專案範本或範例包含已包含Command類別的單一 C# 檔案。 您可以就地更新。

  1. Command1.cs 檔案重新命名為 InsertGuidCommand.cs,將 類別 InsertGuidCommand重新命名為 ,以更新 CommandConfiguration 屬性。

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

    Placements 會指定命令應該出現在 IDE 中的位置。 在此情況下,命令會放在 Visual Studio 中其中一個最上層選單的 [延伸模組] 選單中。

    建構函式的自變數 CommandConfiguration 是命令的顯示名稱,也就是功能表文字。 顯示名稱會以 % 字元括住,因為它會參考 字串 .vsextension/string-resources.json 資源,以支援當地語系化。

  2. 使用的InsertGuidCommand顯示名稱更新.vsextension/string-resources.json

    {
      "InsertGuidCommand.DisplayName": "Insert new guid"
    }
    
  3. 新增 Icon 屬性。

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

    您可以指定已知的內建圖示,在此案例OfficeWebExtension中,或上傳圖示的影像,如新增Visual Studio命令中所述。 第二個自變數是列舉,決定命令應該如何出現在工具列中(除了其在功能表中的位置外)。 選項 IconSettings.IconAndText 表示顯示圖示和彼此旁的顯示名稱。

  4. VisibleWhen新增 屬性,指定必須套用條件,專案才能向用戶顯示。

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

如需詳細資訊,請參閱 使用規則型啟用條件約束

建立執行方法

在此步驟中,您會實作 命令的 ExecuteCommandAsync 方法,這個方法會定義當使用者選擇功能表項時會發生什麼情況,或按下命令工具列中的專案。

複製下列程式代碼以實作 方法。

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

第一行會驗證自變數,然後我們會建立新的 Guid 來稍後使用。

然後,我們呼叫異步方法 GetActiveTextViewAsync來建立 (ITextViewSnapshottextView這裡的物件)。 會傳入取消令牌,以保留取消異步要求的能力,但此範例中不會示範此部分。 如果我們未成功取得文字檢視,我們會寫入記錄檔並終止,而不需要執行任何其他動作。

現在我們已經準備好呼叫異步方法,將編輯要求提交至Visual Studio編輯器。 我們想要的方法為 EditAsync。 這是 類別的成員 EditorExtensibility ,可讓您與 IDE 中執行中的 Visual Studio 編輯器互動。 Command您自己的InsertGuidCommand類別繼承自的型別具有提供物件存取EditorExtensibility權的成員Extensibility,因此我們可以透過對的呼叫this.Extensibility.Editor()EditorExtensibility取得 類別。

方法 EditAsync 會採用 Action<IEditBatch> 做為參數。 此參數稱為 editorSource

EditAsync 呼叫會使用 Lambda 表達式。 若要細分這點,您也可以撰寫該呼叫,如下所示:

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

您可以將此呼叫視為指定要在 Visual Studio 編輯器程式中執行的程式代碼。 Lambda 運算式會指定您要在編輯器中變更的專案。 batch屬於類型 IEditBatch,這表示這裡定義的 Lambda 運算式會進行一組應該以單位方式完成的變更,而不是由使用者或語言服務的其他編輯中斷。 如果程式代碼執行時間過長,這可能會導致沒有回應,因此請務必限制此 Lambda 運算式內的變更,並瞭解可能導致延遲的任何專案。

AsEditable使用檔案上的 方法,您會取得可用來指定所需變更的暫存編輯器物件。 請將 Lambda 表達式中的所有內容視為要求 Visual Studio 執行,而不是實際執行,因為如使用 Visual Studio 編輯器擴充性中所述,有一個特定的通訊協定可用來處理來自延伸模組的這些異步編輯要求,而且可能會接受變更,例如使用者是否在同時進行變更而建立衝突。

模式 EditAsync 可用來修改一般文字,方法是在「在這裡指定您想要的變更」批注之後指定修改。