.NET ローカル ツールの使い方

この記事は[C# その2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/c-sharp-2) 14日目の記事です。

# .NET Core ツールとは

- [.NET core グローバル ツール](https://docs.microsoft.com/ja-jp/dotnet/core/tools/global-tools)

*.NET Core 2.1*より、NuGetにアップロードされたコンソール アプリケーションをCLI上でインストール/実行/アップデート/アンインストールする仕組みができました。
それらのアプリケーションを総称して「.NET Core ツール」と呼びます。
npmでいう`npm install -g tool`のイメージ。

メリットとしては、以下が挙げられます。

- `dotnet`コマンドが使える=.NET Core SDKが入っているので、ほぼ確実に事前セットアップなしでツールを使える
- (スクリプトコマンドと比べて)プラットフォームの差異を.NET Coreが吸収してくれる
- (従来のNuGetからのインストールと比べて)PATHが通っているので、実行パスが煩雑になりにくい
    - Nuget: `~/.nuget/packages/パッケージ名/バージョン/...`
    - Tool: `~/.dotnet/tools`
- (手動でのツール配布に比べて)NuGetの仕組みをそのまま利用できる
    - ファイルサーバにポン置きするだけでプライベート・リポジトリとして配信できる

## .NET core グローバル ツールの使用例

```sh
# インストール
dotnet tool install -g ツールのパッケージ名

# 実行
# インストール先は.NET Core SDKによりPATHが通っているので、そのまま実行可能
ツールの実行ファイル名 arg1 arg2
# dotnet [コマンド名]で呼ぶように作られている場合
dotnet コマンド名 arg1 arg2

# アップデート
dotnet tool update -g ツールのパッケージ名
# アンインストール
dotnet tool uninstall -g ツールのパッケージ名
```

## .NET Core ローカル ツールとは

npmのグローバルインストールが抱えるのと同様に、.NET Coreのグローバルツールは

- リポジトリごとに使用するツールを変えられない
- 複数人で開発時に、使用するツールのバージョン指定を強制できない

といった問題があります。
これらの問題を解決するために、*.NET Core 3.0 SDK*ではツールをローカルにインストールできる仕組みが用意されました。

ちょっと違うけどnpmでは`npm install --save-dev`のイメージ。

現在英語版を含め**ドキュメントがない**ので、仕様は以下のblogおよびissueを参考にしてください。

- [Announcing .NET Core 3.0](https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0/)
- https://github.com/dotnet/cli/issues/10288

# ローカル ツールを使ってみる

前項にもある通り、**.NET Core SDK 3.0**以降のバージョンを用意してください。

## マニフェストファイルを作成する

パッケージのバージョン管理を行うための`dotnet-tools.json`ファイルを作成します。
プロジェクトのルートで以下のコマンドを実行してください。

```sh
dotnet new tool-manifest
```

実行すると、`.config`フォルダ内に以下のjsonファイルが生成されます。

```json:.config/dotnet-tools.json
{
  "version": 1,
  "isRoot": true,
  "tools": {
  }
}
```

## ツールをローカルにインストールする

`-g`オプションを付けないことでローカルインストールになります。
(前述のjsonファイルがないとエラーになります。)

```sh
dotnet tool install dotnet-format
```

実行後、jsonファイルにインストールしたツールとバージョンが書き込まれます。

```diff:.config/dotnet-tools.json
 {
   "version": 1,
   "isRoot": true,
   "tools": {
+    "dotnet-format": {
+      "version": "3.1.37601",
+      "commands": [
+        "dotnet-format"
+      ]
+    }
   }
 }
```

## ツールを実行する

実行手段や引数などはツールによって異なるため、ツールのドキュメントを確認してください。

```sh
dotnet format
```

## ローカル ツールを復元する

リポジトリからクローンした直後など、まだローカルツールをセットアップしていない場合は、下記のコマンドを実行します。
`dotnet-tools.json`の内容をチェックして、指定されたバージョンのツールがインストールされます。
(npmでいう`npm install`のイメージ)

```sh
dotnet tool restore
```

# 有用なツール類

自分は以下のツールをよく使っています。

- [dotnet-format](https://github.com/dotnet/format)
    - Lintツール
    - ルールは`.editorconfig`をベースに拡張([記法](https://docs.microsoft.com/ja-jp/visualstudio/ide/editorconfig-code-style-settings-reference))
- [dotnet-t4](https://github.com/mono/t4)
    - Monoベースで作られたテキストテンプレートエンジン(`.tt`)
    - vscodeでもT4できるようになる

他にも、有用なツールの一覧が以下にまとめられています。

- https://github.com/natemcmaster/dotnet-tools

# ツールを自作する

~~時間があれば作ります~~
「Postgresqlのテーブル一覧情報を取得し、POCOなクラスを生成する」ツールを作っていましたが、ものの見事にGit for Windowsの`AutoCrLf`機能でハマってしまったので間に合わず。
作りかけ状態のリポジトリがこちらになります。
[dotnet-pg-entity](https://github.com/nogic1008/dotnet-pg-entity)

# まとめ
- .NET core CLIからツールを使える仕組みがあるよ
- まだドキュメント化されていないけどローカルインストールもできるようになったよ
- 有用なツールを使って、コードの品質や生産性を上げていきましょう