sci

最果て風呂

CSharp のプロジェクトを dotnet で

この記事に関連するお話です。

dotnetC# のパッケージ作成をしてみます。手元にあるものが 1.0 系なので古いけど、雰囲気を味わうことはできるでしょう。

雛形の作成

雛形のディレクトリは作成してくれないので、あらかじめ作業ディレクトリを作成しておき、その中でコマンドを入力します。

mkdir csmto
cd csmto
dotnet new console

作成されるのは Program.cscsmto.csproj。バージョンが古いので、dotnet restore を実行しておく必要があります。こうすると project.assets.json 等を生成してくれるのです。

プロジェクトの設定

今のところ特に設定すべきものはありません。

プロジェクトの実装

mono とは異なっているので、実装の変更をすることになりました。次の部分で苦労してしまいました。

foreach statement cannot operate on variables of type 'csmto.Program.ArrayList' because 'csmto.Program.ArrayList' does not contain a public definition for 'GetEnumerator' [csmto]
Program.cs(85,38): error CS1579: foreach statement cannot operate on variables of type 'csmto.Program.ArrayList' because 'csmto.Program.ArrayList' does not contain a public definition for 'GetEnumerator' [/Users/home/csmto/csmto.csproj]

The build failed. Please fix the build errors and run again.

調べてみると、dotnet core だと気楽にリストを foreach できないみたい。ArrayList 自体が古い規格のものらしく、最近は List を使うらしいです。そこで ArrayList を List<List> で実装し直すことにしました。

次のようにして実行することができます。-- で引数を run に渡せます。後者の方が速いです。

dotnet run -- tradkana Hidoi.txt
dotnet bin/Debug/netcoreapp1.1/csmto.dll tradkana Hidoi.txt

テストの記述

今のままではダメみたいなので、次のようにしてディレクトリ構成を変更しました。

  • CsMto ディレクトリを作成してファイルを移動 (名前も csmto -> CsMto へ)。
  • dotnet new sln を実行。csmto.sln ファイルが作成される。
  • dotnet sln add CsMto/CsMto.csproj を実行して sln に追加。
  • mkdir CsMto.Tests でテスト用のディレクトリを作成し、その中に入って dotnet new xunit を実行してテストを作成。CsMto/test はこちらに移動。
  • UnitTest1.cs と CsMto.Tests.csproj ファイルが作成されている。この CsMto.Tests.csproj に CsMto を認識させるために dotnet add reference ../CsMto/CsMto.csproj を実行。
  • さらに上の階層に移動して dotnet sln add CsMto.Tests/CsMto.Tests.csproj で sln に追加。
  • とりあえず dotnet restore を実行しておく。

csmto 内で dotnet build を実行すると、次のようにアプリとテストの両方をビルドしてくれました。

> dotnet build
Microsoft (R) Build Engine version 15.1.1012.6693
Copyright (C) Microsoft Corporation. All rights reserved.

  CsMto -> /Users/home/csmto/CsMto/bin/Debug/netcoreapp1.1/CsMto.dll
  CsMto.Tests -> /Users/home/csmto/CsMto.Tests/bin/Debug/netcoreapp1.1/CsMto.Tests.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:03.27

dotnet test を実行すると下記のエラーに。

Couldn't find a project to run test from. Ensure a project exists in /Users/home/csmto.
Or pass the path to the project

CsMto.Tests に移動して dotnet test を実行するとうまくいきました。

> dotnet test
Build started, please wait...
Build completed.

Test run for /Users/home/csmto/CsMto.Tests/bin/Debug/netcoreapp1.1/CsMto.Tests.dll(.NETCoreApp,Version=v1.1)
Microsoft (R) Test Execution Command Line Tool Version 15.0.0.0
Copyright (c) Microsoft Corporation.  All rights reserved.

テスト実行を開始しています。お待ちください...
[xUnit.net 00:00:00.7561953]   Discovering: CsMto.Tests
[xUnit.net 00:00:00.9055221]   Discovered:  CsMto.Tests
[xUnit.net 00:00:00.9710108]   Starting:    CsMto.Tests
[xUnit.net 00:00:01.1647042]   Finished:    CsMto.Tests

テストの合計数: 1。成功: 1。失敗:0。スキップ: 0。
テストの実行に成功しました。
テスト実行時間: 2.1563 秒

あとはテストを実装していくだけ。と気楽に考えていたら、別のクラス (CsMto) のメソッドが実行できないのでした。Mto.cs 内で辞書作成部分、文字列置換部分を MtoLib というクラスに分け、引数処理の部分は Program クラスのままにしました。

UnitTest.cs からは CsMto.MtoLib.CreateDictionary() でアクセスすることができるようになりました。ReplaceTextInFileCar 等は Console.Write で出力しているのをやめて、void 型から string 型に変更し、変換した文字列を返す関数としました。これでテスト側で受け取ることができるようになり、比較が可能となりました。

内部辞書の比較部分で苦労することに。結局下記のようにすれば作成できることがわかりました。

List<List<string>> validdic = new List<List<string>>() {
    new List<string>() {"こんにちは", "こんにちわ"},
    new List<string>() {"こんばんは", "こんばんわ"},
    new List<string>() {"たなこふ", "(´・_・`)"},
    new List<string>() {"くどう", "せやかて"},
    new List<string>() {"高鴎福吉", "髙鷗福𠮷"},
    new List<string>() {"葛", "葛󠄀"},
    new List<string>() {"ヒラギノ角ゴ", "ヒラギノ角ゴ"},
    new List<string>() {"김", "김"},
    new List<string>() {"🍣", "🍻"},
    new List<string>() {"ありがとう", "おおきに"}
};

いちいちテストディレクトリに移動しなければなりません。ソリューションディレクトリ内でテストを実行するには、次のようにプロジェクトディレクトリの .csporj を指定してやればいいのでした。

dotnet test CsMto.Tests/CsMto.Tests.csproj

実行する時も同様で --project オプションで渡します。

dotnet run --project CsMto/CsMto.csproj

パッケージの作成

nuget pack -c Release を実行すると CsMto/bin/Release/CsMto.1.0.0.nupkg が作成されます。テストは警告が出るものの、CsMto.Tests/bin/Release/CsMto.Tests.1.0.0.nupkg は作成されました。これらを nuget.org 等で配布することになるのですが、GitHub などから Git リポジトリとして直接配布することはできないみたいです。

GitHub からのインストール

無理っぽい。