簡単な拡張機能を作成する

最初の拡張機能の作成では、VisualStudio.Extensibility プロジェクト テンプレートを使用して拡張プロジェクトを作成する方法と、Visual Studio の実験用インスタンスでビルドしてデバッグする方法について学習しました。

このチュートリアルでは、Visual Studio エディターで何かを実行する単純なコマンドを使用して拡張機能を作成する 方法について説明します。 この場合、新しく生成された GUID が挿入されます。 また、GUID 拡張機能が有効になっているファイルの種類を Visual Studio に通知する方法と、新しいコマンドをツール バーまたはメニュー項目として表示する方法についても説明します。

このチュートリアルの完成したサンプルは、ここで見つけることができます

このチュートリアルには、次の手順が含まれています。

コマンドを構成する

この手順では、コマンドを構成して配置するためのオプションについて説明します。 コマンドをホストする目的は、メニュー項目やコマンド バー ボタンの追加など、何らかの方法でコマンドをユーザーに公開することです。

最初の拡張機能の作成チュートリアルで作成したプロジェクト テンプレートまたはサンプルは、既にクラスを含む 1 つの C# ファイルでCommand構成されています。 その場で更新できます。

  1. ファイルの名前を Command1.cs 変更し InsertGuidCommand.cs、クラス InsertGuidCommandの名前を変更し、プロパティを更新します CommandConfiguration

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

    Placements は、IDE でコマンドを表示する場所を指定します。 この場合、コマンドは Visual Studio の最上位メニューの 1 つである [拡張機能] メニューに配置されます。

    コンストラクターの 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),
    };
    

    Visual Studio の追加コマンドの説明に従って、既知の組み込みアイコン (この場合OfficeWebExtension) を指定するか、アイコンの画像をアップロードできます。 2 番目の引数は、コマンドをツール バーに表示する方法を決定する列挙体です (メニューの場所に加えて)。 このオプション 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 行を作成します。

次に、非同期メソッドGetActiveTextViewAsyncITextViewSnapshottextView呼び出して (ここではオブジェクト) を作成します。 非同期要求を取り消す機能を保持するためにキャンセル トークンが渡されますが、この部分はこのサンプルでは示されていません。 テキスト ビューが正常に表示されない場合は、ログに書き込み、他の操作を行わずに終了します。

これで、Visual Studio のエディターに編集要求を送信する非同期メソッドを呼び出す準備ができました。 私たちが望む方法は.EditAsync これは、IDE で実行中の EditorExtensibility Visual Studio エディターとの対話を可能にするクラスのメンバーです。 独自InsertGuidCommandのクラスが継承する型にはCommand、オブジェクトへのアクセスを提供するEditorExtensibilityメンバーExtensibilityがあるため、クラスへのEditorExtensibility呼び出しthis.Extensibility.Editor()で取得できます。

このメソッドは EditAsync パラメーターとして受 Action<IEditBatch> け取ります。 このパラメーターは、editorSource

ラムダ式を使用する EditAsync 呼び出し。 これを少し分解するために、次のようにその呼び出しを書くこともできます。

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 エディター プロセスで実行するコードを指定していると考えられます。 ラムダ式は、エディターで変更する内容を指定します。 型は batchIEditBatchここで定義されているラムダ式が、ユーザーまたは言語サービスによる他の編集によって中断されるのではなく、単位として実行する必要がある小さな変更セットを行っていることを意味します。 コードの実行時間が長すぎると応答しなくなる可能性があるため、このラムダ式内の変更を制限し、遅延につながる可能性のあるものを理解することが重要です。

ドキュメントのメソッドを AsEditable 使用して、必要な変更を指定するために使用できる一時エディター オブジェクトを取得します。 ラムダ式のすべてが、Visual Studio エディターの拡張機能の使用に関するページで説明されているように、拡張機能からこれらの非同期編集要求を処理するための特定のプロトコルがあり、ユーザーが同時に変更を行って競合を作成している場合など、変更が受け入れられない可能性があるため、実際に実行するのではなく、Visual Studio が実行するための要求と考えてください。

パターンは EditAsync 、"ここで必要な変更を指定する" コメントの後に変更を指定することで、テキスト全般を変更するために使用できます。