yotiky Tech Blog

とあるエンジニアの備忘録

LINQPad - 拡張メソッド(My Extensions相当)をファイル分割して管理する

TL;DR

  • My Extensionsファイルに拡張メソッドを実装するとどこからでも使える拡張メソッドを定義できる
  • ファイルのコードが増えても、My Extensions ファイル以外では定義することができない
  • そこで Plugins を利用して、ファイルを分割して拡張メソッドを管理する環境を整える

目次

検証環境

手順

プロジェクトの作成

まず、My Queriesのフォルダと Plugins のフォルダの場所を、LINQPadのPreferencesで確認する。

クラスライブラリのプロジェクトを、LINQPad Queriesフォルダ配下に作成する。
今回は、MyExtensionsフォルダを作ってその下に作成。

フレームワーク .NET 7を選択。

プロジェクトのセットアップ

プロジェクトの参照マネージャーを開いて、LINQPad.Runtime.dllの参照を追加する。

または、NuGetからも取得できる。

続いて、プロジェクトのプロパティを開く。

ビルド後のイベントで、dllをPluginsフォルダにコピーするように設定しておく。

copy /y "$(ProjectDir)bin\$(Configuration)\net7.0\ClassLibrary1.dll" "$(ProjectDir)..\..\..\..\LINQPad Plugins\NetCore3"

ビルドしてみて、LINQPad Pluginsフォルダの下にdllが出力されてるか確認する。

編集用 linq ファイルの作成

csファイルは、LINQPadにも表示されるため直接編集が可能。

拡張メソッドをビルドするためにいちいちソリューションを開くのは面倒なので、編集用のlinqファイルを用意して、LINQPadで実装できるようにする。 Class1.csと同じフォルダにExtensionsEditorという名前で作成。

#load "MyExtensions\ClassLibrary1\ClassLibrary1\Class1.cs"

void Main()
{
}

void DeleteDll()
{
    File.Delete(Path.Combine(Util.MyQueriesFolder, @"..\LINQPad Plugins\NetCore3\ClassLibrary1.dll"));
}

void BuildProject()
{
    var msbuild = @"C:\Program Files\Microsoft Visual Studio\2022\Professional\Msbuild\Current\Bin\MSBuild.exe";
    var sln = Path.Combine(Util.MyQueriesFolder, @"MyExtensions\ClassLibrary1\ClassLibrary1.sln");

    var psInfo = new ProcessStartInfo
    {
        FileName = msbuild,
        Arguments = $"\"{sln}\"",
        CreateNoWindow = true,
        UseShellExecute = false,
        RedirectStandardOutput = true,
    };

    var p = Process.Start(psInfo);
    p.StandardOutput.ReadToEnd().Dump();
}

#load でcsファイルを直接読み込むようにする。
Pluginsフォルダにdllが存在すると内容が重複してエラーになってしまうため、dllを削除するためのDeleteDllを用意しておく。拡張メソッドを編集する時に呼び出してdllを消す。

ビルドも直接実行できるように、BuildProjectを用意しておく。 MSBuild.exe は利用しているVisual Studioのインストール先に置かれている。(MSBuild 17.0 の新機能

拡張メソッドの実装が終わったら、BuildProjectを実行してdllを配置する。 標準出力をリダイレクトしているので、ビルドの出力結果を確認できる。

拡張メソッドを実装する

Class1.csを開いて拡張メソッドを実装する。

雑なサンプルを用意。

using LINQPad;

public static class HogeExtensions
{
    public static void Hoge(this string s)
    {
        "hoge".Dump();
    }
    public static void Fuga(this string s)
    {
        (s + " Fuga").Dump();
    }
    public static void Piyo(this string s)
    {
        "piyo piyo".Dump();
    }
}

ExtensionsEditor.linqを開いて動作確認する。