続 .NET Standard とは何か?

.NET Standard とは何か? | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/8218

の続編です。1年前位に、.NET Standard が発表されて、その後どうなるのかと思いつつ、.NET Core 2.0 のプレビュー版が出てきて、最近 Rasbian 上で .NET Core 2.0 を動かしてみて分かったことをいくつかまとめます。

PLCは最小公倍数で、.NET Standardは最大公約数だ

せまっ苦しいPCL(Potable Class Library)では、なかなか大変なことになっているので、いっそのこと、.NET Framework、.NET Core、UWP な .NET Runtime を大まかに含めてしまったのが「.NET Standard」であるというのは、概ね合っています。完全に包括しているわけではない(たまに、.NET Frameworkで含まれているクラスが .NET Standard に含まれていないので)のですが、概ね含まれています。

大まかに.NETの動作環境を考えると、

  • .NET Framework は、Windows の Desktop で動く
  • .NET Core は、Linux で動く
  • .NET の Runtime は、UWP(Windowsストア)な環境で動く
  • .NET の Runtime は、Windows Mobile で動く

更に、

  • Mono が Linux 上で動く。
  • Mono が、macOS 上で動く。
  • Xamarin.MAc が macOS 上で動く。
  • Xamarin.Android(MonoDroid)が、Android 上で動く。
  • Xamarin.iOS(MonoTouch)が、iOS 上で動く。

という現状があります。Xmarinな環境はベースがMonoなので、Android/iOSに限らずLinuxやmacOSでも動作する点で範囲が広いわけですが、いざ、Winodwsも含めて共通ライブラリを作るとPLC Hellに陥ります。結局のところ、最小公倍数なクラス群をまとめる形になるので、せまっ苦しくなります。

実は、.NET Standardが最大公約数的とはいえ、Windowsのデスクトップ環境(WindowsフォームやWPFとか)は入っていないし、逆にXamarin.Macで使われるようなCocoaな機能は入っていません。なので、主に非グラフィックな機能を集めることになります。一方で、Xamarin.Formsが、iOS/Android/UWPをカバーし始め、Windows(.NET Framework)のWPF/UWPと括弧付きですがSilverlightを含めて、「XAML Standard」という発想が出てくるのは無理からぬことです。が、まあそれはさておき。

じゃあ、なんとなくですが、PCLよりも広い感じで使える.NET Standardということで、どんな風に使うのか?というのを具体的に考えます。

Rasbianで.NET Core 2.0を動かしてみる

.NET Core 2.0 から実行環境にRaspberry PiのARMv7/8な環境がサポートされるようなりました。もともと、RasbianではMonoが動くのですから、.NET Coreが動かないというのも変な形なのですが、まあ動かなかった訳です。で、現時点ではビルドはできないけれども(つまりコンパイラが動かないとうこと…なのか)、実行だけはできる環境が整いました。

さて、ラズパイ上でGPIOを制御する(Lチカする)ことなるので、ハードウェアを触るとここは RaspberryPi.Net を使いました(Raspberry#IOのほうが有名なのですが、これがどうも動かないもので)。さらに、ハードウェアそのものを動かすために bcm2835 といチップを操作する C言語のライブラリを扱います。つまり、次の3つの部分に分かれるわけです。

  • メインのプログラム(C#)
  • RaspberryPi.Netクラスライブラリ(C#)
  • bcm2835ライブラリ(C言語)

bcm2835ライブラリは、C言語で書かれているのでRaspberry Piべったりの制御ということが分かるので、当然ながら他のマシンとの互換性はありません。
メインのプログラムとRaspberryPi.NetクラスライブラリはC#で書かれているので、先に書いたような色々な.NETな実行環境で動かすことが可能です(実際のところ、GPIO制御が入るので、ラズパイ上でしか動かないのですが)。

最初に考えるのは、ラズパイ上なので、この2つをMonoでビルドすることです。Monoはラズパイ上で動いているので、そのまま動きますよね。

次に考えたのは、せっかく .NET Core 2.0 がラズパイ上で動くようになったので、メインのプログラムとRaspberryPi.Netクラスライブラリの両方を .NET Core 2.0 でビルドし直すということです。
この環境で動かすこともできるようになりました。

ふと、じゃあ .NET Standard 2.0(.NET Core 2.0をサポートしているので)を含めるとどうなるのだろうか?ということを考えてみると、

  • メインのプログラム(C#) → .NET Core 2.0
  • RaspberryPi.Netクラスライブラリ(C#)→ .NET Standard 2.0
  • bcm2835ライブラリ(C言語)

という組み合わせが考えられます。
RaspberryPi.Netクラスライブラリは汎用的に(その他のAndroidやiOSなど…GPIOを使えないけど)使うことを考えて .NET Standard でビルドをしておき、そのライブラリをメインの .NET Core で作った実行ファイル(Rasbian上なので拡張子はexeではありませんが)で利用します。

実際、この組み合わせで動作を確認しています。
これで、なんとなくわかると思いますが、

  • 最終的な実行部分(メインプログラム)は、各OSに即した.NET環境を使う
  • 中間のライブラリは一括して.NET Standardで作る。
  • 個別の制御はC言語や即した.NET環境を使う

という作り分けになるでしょう。

中間のライブラリを片っ端から.NET Standardにする

発想的には、こんな風に.NET Standardがサンドイッチ状態になります。

実際にはフロントが要らない場合もあるし、その環境でしか動かさないのであれば無理に.NET Standarでビルドをする必要はないのですが、中間の部分を.NET Standardでビルドをしておいて、NuGetのようにダウンロードできるようにしておけば、全ての.NET実行環境で使えることになるでしょう。

.NET Standardなライブラリの作り方

Visual Studio 2017 Update3プレビュー版では、.NET Standard 2.0 が使えます。プロジェクトのテンプレートを見ると非常に簡単で「クラスライブラリ」しかありません。

理由は簡単です。先に書いた通り、フロントUIでもないし、個別のハードウェア寄りでもない中間層を受け持つので「クラスライブラリ」だけで十分なのです。

既存のプロジェクトを.NET Standardに変えたい場合は、*.csporj を開いて、以下のように変更するだけです。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
</Project>

コンパイル対象のファイルは、フォルダー内のC#の全てのファイルが自動的に対象になります。少々乱暴な気がしますが、プロジェクトの設定が非常に簡単になっています。

そんな訳で、これを踏まえて Rasbian + .NET Core/Standard の組み合わせを後日考察。

カテゴリー: 開発 パーマリンク