Xamarinでの開発も1年半くらい経ったので今回はXamarin.FormsでのSharedプロジェクトが何かと便利っていう話を書きたいと思います
基本的にXamarin.Forms開発では.Net Standard(PCL)が推される傾向にあるのでそれに対する挑戦状みたいなものです。ちょっと面白い技も書いてみたので見てみてください
どんな種類のプロジェクトがあるの?
Xamarin.Formsには
- .Net Standardプロジェクト(以前はPCLプロジェクト)
- Sharedプロジェクト
この2つの作成方法があります。
以下にプロジェクトをビルドした時のアセンブリについて書きます
.Net Standardプロジェクト
- 共通コード用のアセンブリ
- App.dll
- プラットフォーム固有コード用のアセンブリ
- App.iOS.dll
- App.Android.dll
- App.UWP.dll
Sharedプロジェクト
- 共通コード用のアセンブリ
- なし
- プラットフォーム固有コード用のアセンブリ
- App.iOS.dll
- App.Android.dll
- App.UWP.dll
このように、Sharedプロジェクトでは共通コード用のアセンブリが存在しません。じゃあ共通コード書けないじゃん!って思うかもしれませんが、それも実は違います。Sharedプロジェクトではアセンブリは存在しませんが共通コードを書くことのできるプロジェクトが追加されます。
もしかしたらデスクトップの開発等に慣れている方はかなり混乱するかもしれません。アセンブリ生成されないのにコード書いちゃったら、どう参照するんだ!!ってなるかもしれません。
Sharedプロジェクトのコードはビルド時にそれぞれのアセンブリへコードがコピーされます。試しに以下のようなプロジェクトをAndroidでビルドしてみましょう(初めて日本語を含めたクラスを作りました...)
これをビルドするとdllが生成されるので、これをILSpyで覗きたいと思います
御覧ください!見事に"Sharedクラスだよ"っていう名のクラスが追加されていますね!
このようにSharedプロジェクトを使うと自動でコピーされるので.Net Standardプロジェクトと比較してアセンブリが1つ減ることがわかります。Xamarinでも特にAndroidはアセンブリが数十個なんて当たり前(初期段階で11個ありました)なので、ほんの少しですがアセンブリを減らすことで起動速度の高速化も見込めるかと思います。
さらに!あんまりオススメできる方法ではないかもしれませんがSharedでは共通コード部分でもネイティブのコードを書くことが可能になります。
上に書いたとおりコードがコピーされる仕組みのため以下の画像のようにビルド構成をiOSのみにすればiOSのネイティブ処理を書き込めます。もちろんこの状態でAndroidの方でもビルドしようとすれば流石にビルドエラーを起こしますが、実際に開発してみると一時的にネイティブで書いて動作を確認したい時がたまにあるので何かと便利です。しかもIntelliSenseも効くので結構いい感じです
面白い技とは?
この他にもXamarinにはDependencyServiceなるものやデバイス情報の取得に利用されるDeviceクラスがありますが、これらの機能を利用するためにはForms.Initを呼ぶ必要があります。
しかし起動時に非同期で処理等を行う場合など、どうしてもInit前にデバイス情報が欲しい場合には、共通コードがコピーされる特性を活かして、それぞれのプロジェクトに名前空間&クラス名&メンバーを全て同じにしたクラスを配置すると共通コードからInitを呼び出さずにデバイス情報を取得するというトリックも使えます。
このトリックはおそらく.Net Standardでは不可能な技かと思います。
デメリットは?
考えてみましたが、あまりデメリットが浮かびません。強いて言えば上に述べた事と反対にネイティブ処理が書ける影響で、しっかりコードの管理をしないと共通コードとネイティブコードが混在するような事態が起こりえます。また、面白い技に書いてあるものもせいぜい1つのクラスにまとめておかないと保守性に欠ける点が挙げられます。
それと
https://docs.microsoft.com/ja-jp/xamarin/cross-platform/app-fundamentals/code-sharing
に書いてあるようにリファクタリングを行う際には共通コード部のみで参照している部分だけにしないと、アクティブになっていないプロジェクトで参照が変更されずエラーが起きることがあります。
NuGetや外部アセンブリの追加はどうするの?
私も最初はかなり疑問に思っていましたが、大したことはありません。各プラットフォーム用のアセンブリに参照をそれぞれ追加すれば共通コード部でも利用可能になります。Visual StudioにはソリューションのNuGetパッケージ管理なるものがあるので、あまり手間もかかりません。
結論
Xamarin.FormsはSharedがオススメ