.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 を開いて、以下のように変更するだけです。
1 2 3 4 5 | < Project Sdk = "Microsoft.NET.Sdk" > < PropertyGroup > < TargetFramework >netstandard2.0</ TargetFramework > </ PropertyGroup > </ Project > |
コンパイル対象のファイルは、フォルダー内のC#の全てのファイルが自動的に対象になります。少々乱暴な気がしますが、プロジェクトの設定が非常に簡単になっています。
そんな訳で、これを踏まえて Rasbian + .NET Core/Standard の組み合わせを後日考察。