背景
最近、ServiceScopeの内部動作ロジックを調査していたところ、関連資料が非常に少なく、IOC関連の記事でCore時代の公式依存性注入の使い方が説明されている程度でした。そこで、やはりソースコードを確認することにしました。該当のソースコードはMicrosoft.Extensions.DependencyInjectionライブラリ内にあり、src/libraries以下にあります。少し読んでみたところ、内部でサービスを解決する際に行ったり来たりしており、コードを追いながら整理するのは非常に厄介でした。
C#でも、Javaのようにソースコードをスムーズにデバッグできる方法はないのでしょうか?
実際の効果
なんと、ありました! 余談はさておき、画像をご覧ください。


非常に高速で、ローカルコードをデバッグしているかのようです。 逆コンパイルしたものとは比べ物にならないスムーズさです!
公式プロジェクトではどのような魔法を使っているのか、ここでは直接ソースコード(図中の外部ソース)を取得できていますが、自分で開発したプロジェクトではこれが実現できません。
具体的な手順
この部分について公式の説明はありますが、いくつかの重要なポイントが抜けており、非常に時間がかかりました。以下で詳しく説明します。
- PS1: 主にWindows VSを対象としています。他のプラットフォームでも同様の手順になるはずです。
- PS2: 主にDIの構築ロジックを確認しています。この部分はバージョン間で大きな差がないため、6.0を直接取得しました。
1. 公式リポジトリを開く
確認したいブランチのコードをローカルにクローンします。私が主に確認したのは以下のものです。

2. ビルド手順を確認する

3. 対象プラットフォームの基本環境をインストールする

Windows VSプラットフォームでは次のようにインストールします。


次に「詳細を表示」をクリックし、表示されるプロンプト(XXXXXをインストールできませんなど)は無視して、「変更」をクリックします。
この手順について、公式では「互換性のあるSDKのバージョンをインストールすればよく、完全に一致させる必要はない」としています。通常、開発用マシンには.NET Frameworkと.NETのSDKがいくつかインストールされていますので、一般的には問題ありません。私は .NET Framework 4.0 ターゲットパック + 4.7.2 ターゲットパック + .NET 6.0 SDK をインストールしました。
[重要] 4. 該当ライブラリの復元
エクスプローラーでruntimeのルートディレクトリに移動します。このbuild.cmdを覚えておいてください。

右クリックしてコマンドラインまたはPowershellを開き、次のように実行します。

スクリプトがps1ファイルをダウンロードして自動実行されます。待機していれば、必要なライブラリと依存する基本パッケージが自動的に復元されます。
公式のコード構造にはnuget設定と出力ディレクトリが既に整備されているため、追加の設定は不要です。次の手順でコンパイルします。
5. 対象ライブラリのDLLファイルを生成する
該当ライブラリのコードファイルを開きます。

右クリックしてコマンドラインまたはPowershellを開き、次のように実行します。

コンパイルが完了するまで待ち、以下のディレクトリを確認します。

各ライブラリはartifacts以下に生成され、アーキテクチャごとにフォルダが分かれています。この時点で、テストプロジェクトでこのDLLを直接参照して、快適にデバッグできます。
[オプション] 6. 依存ライブラリファイルを生成する
今回はMicrosoft.Extensions.DependencyInjectionをデバッグしたかったのですが、NuGetで確認すると、抽象定義パッケージMicrosoft.Extensions.DependencyInjection.Abstractionsにも依存していることがわかります。デバッグ中に行き詰まらないよう、このパッケージも同様の手順で生成しました。
その他
- 調査中に、VSで直接コンパイルする方法もあることがわかりましたが、いくつかの設定が必要で理解できなかったため、この方法を採用しました。すべてのパッケージをコンパイルする必要はありません。
VS Codeでも可能ですが、主にVSを使用しているため、この部分は割愛します。build.cmdスクリプトに引数を指定しないとすべてのパッケージがコンパイルされるようです。不要だったのでスキップしました。