ツナ缶雑記

ぐうたらSEのブログです。主にマイクロソフト系技術を中心に扱います。

Visual Studioで巨大なソリューションを扱うときに便利な機能

f:id:masatsuna:20210810221019p:plain

ここのところかかわっているプロジェクトでは、 1 ソリューションのプロジェクト数が 500 を超えていて、 Visual Studio でソリューションを開くことがなかなか困難なレベルになっています。 そういう巨大なソリューションを取り扱う場合、 Visual Studio 2019 以降で使える便利な機能がありますので紹介します。

環境

プロジェクトをアンロードした状態でソリューションを開く

巨大に育ってしまったソリューションの場合、そもそも貧弱なマシンでは Visual Studio で開くことができません。 ソリューションファイルをダブルクリックして、ソリューションを直接 Visual Studio で開く、というオペレーションはあきらめましょう。 そういったときは、先に Visual Studio を起動して、起動メニューからソリューションを開くメニューを選択するか、メニューバーから以下のようにソリューションを開くメニューを選択します。

f:id:masatsuna:20210807201242p:plain
メニューバーからソリューションを開く

開くソリューションを選択する際、 [プロジェクトを読み込まない] にチェックを入れてから開きましょう。 これで全プロジェクトをアンロードした状態で開くことができるため、大きなソリューションでも問題なく開けます。

f:id:masatsuna:20210808194418p:plain
プロジェクトをアンロードした状態でソリューションを開く

プロジェクトを読み込む

このようにしてソリューションを開くと、全プロジェクトがアンロードした状態になります。

f:id:masatsuna:20210808195833p:plain
すべてアンロードした状態で開く

実行に必要なプロジェクトを右クリックして、 [プロジェクトの再読み込み] を選択することでロードすることができます。

f:id:masatsuna:20210808200007p:plain
プロジェクトの再読み込み

これで大量のプロジェクトがあるソリューションでも、必要なプロジェクトだけを選択してロードすることができます。

依存関係にあるプロジェクトをまとめて読み込む

ソリューション構造が複雑だったり、 1 つのプロジェクトが別のプロジェクトをいくつも参照するような構造の場合、ひとつひとつプロジェクトを読み込むのは非常に手間です。 そういった場合は、プロジェクトを右クリックして [依存関係のあるプロジェクトを再読み込み] を選択しましょう。

f:id:masatsuna:20210808200203p:plain
依存関係のあるプロジェクトを読み込む

これで、依存関係のあるプロジェクトをまとめてロードできます。 スタートアッププロジェクトに対してこれを行うことで、最低限のプロジェクトだけをロードできます。

f:id:masatsuna:20210808200606p:plain
必要なプロジェクトのみを再読み込み

ソリューションフィルター

必要なプロジェクトだけ読み込んだ状態にすると、 Visual Studio を再起動しても、同じ状態を再現できます。 しかし、この読み込み設定を、ほかの人と共有することができません。 他の人と設定を共有したい場合は、ソリューションフィルターと呼ばれる機能を使いましょう。

一部のプロジェクトをアンロードした状態で、ソリューションを右クリックして [ソリューションフィルターとして保存] を選択します。

f:id:masatsuna:20210808204315p:plain
ソリューションフィルターとして保存

すると、「*.slnf」という拡張子のファイルを保存できます。 これで、アンロードした状態をファイルに保存できます。

f:id:masatsuna:20210808204550p:plain
*.slnfファイルとして保存

*.slnf ファイルは、 JSON 形式のファイルです。 元のソリューションファイルは何だったのかと、読み込んでいるプロジェクトの一覧が以下のように記述されています。

{
  "solution": {
    "path": "eShopOnWeb.sln",
    "projects": [
      "src\\ApplicationCore\\ApplicationCore.csproj",
      "src\\BlazorAdmin\\BlazorAdmin.csproj",
      "src\\BlazorShared\\BlazorShared.csproj",
      "src\\Infrastructure\\Infrastructure.csproj",
      "src\\Web\\Web.csproj"
    ]
  }
}

*.slnf ファイルは、 Visual Studio に直接読み込ませて使用することができます。 上記のようにして作成した *.slnf ファイルを Visual Studio で開くと、以下のようになります。

f:id:masatsuna:20210810211908p:plain
*.slnf ファイルを開く

アンロードしたプロジェクトは、その存在すら見えないようになっているのが特徴です。 このまま実行すると、ロードされているプロジェクトだけがビルドされます。

アンロードしたプロジェクトを再表示する

ソリューションフィルターを利用すると、一部のプロジェクトのみフィルタリングして表示することができます。 フィルタリングの結果、非表示になってしまったプロジェクトを再表示することもできます。

アンロードされたすべてのプロジェクトを再表示する場合は、ソリューションを右クリックして [アンロードされたプロジェクトを表示] で表示できます。

f:id:masatsuna:20210810212340p:plain
アンロードされたプロジェクトを表示

ソリューションフォルダーでソリューション内を階層化している場合は、ソリューションフォルダーの単位でも同様の操作ができます。 ソリューションフォルダーを右クリックして [フォルダーの再表示] を選択しましょう。

f:id:masatsuna:20210810215044p:plain
フォルダーの再表示

これでアンロード状態のプロジェクトを再表示できます。

複数の *.sln ファイルを用意することとの違い

こういった問題が発生したとき、数年前までは複数の *.sln ファイルを目的別に用意して対処するケースが多かったのではないでしょうか。 たしかにそれでも対処はできていたのですが、開発用の *.sln ファイルが乱立しやすく、回避策の色合いが濃かったように思います。 複数の *.sln ファイルを用意してしまうと、全部入りソリューションのプロジェクト追加/削除を忘れてしまうことが(私は)よくありました。 ソリューションフィルターなら、元の *.sln をフィルタリングしているだけなので、全部入りソリューションファイルの破壊を防ぐことができます。

ただし、プロジェクトを追加したり削除したりしたときは、ソリューションフィルターファイルの更新を行わなければならないことに注意しましょう。 ソリューションフィルターを使ってソリューションを開いている場合、ソリューションフィルターに影響のあるような更新をソリューションに対して行うと、以下のようなメッセージがソリューションエクスプローラーに表示されます。

f:id:masatsuna:20210810215539p:plain
ソリューションフィルターの更新

ここで [ソリューション フィルターの更新] リンクを押下すると、開いているソリューションフィルターに関しては設定を更新してくれます。 複数のソリューションフィルターを用意している場合、別のソリューションフィルターには変更が反映されないため注意しましょう。

またソリューションフィルターは、表示するプロジェクトをフィルタリングするためにあります。 そのため、存在しないプロジェクトを前述した JSON ファイルの projects に設定しても、その設定は無視されてしまいます。 このあたりも気を付けておかないと、無駄なゴミ設定がたまってしまうかもしれません。 用法容量には気を付けないといけませんね。

まとめ

今回は巨大なソリューションを取り扱うプロジェクトで便利なソリューションフィルターを紹介しました。 巨大なソリューションをチーム開発するようなユースケースで、非常に使い勝手の良い機能だと思います。 ただし、 *.slnf ファイル自体のメンテナンスをおざなりにすると、設定がカオスになっていく可能性も感じます。 *.slnf ファイルを開発者間で共有する場合は、しっかりメンテナンスすることを意識したほうがよさそうです。 逆に言うと、必要がなければ構成管理に紛れ込まないように .gitignore とかでコントロール*1したほうが良いかもしれませんね。

*1:GitHub とか Azure DevOps で Git リポジトリを作ったときに生成できる .gitignore には、2021/08/10 現在、 *.slnf を除外する設定は入っていません。