例えばMicrosoft.AzureのStorageのライブラリなんかがXamarin.AndroidとXamarin.iOSには対応してるけどPCLには対応してないといった感じです。
被害者がここに。
@chomado ウワアアあああああ
— ちょまど@MS入社して8ヶ月 (@chomado) 2016年12月8日
ああああああああああああ
Xamarin .Forms PCL の私 爆死\(^o^)/#JXUG <- Xamarinでの開発時の困った時に押すボタン pic.twitter.com/n5yi8UAPba
対応方法
ということで対応方法ですが、id:chomadoさんがちゃんと対応してました。
今日はここまでだな!めっちゃコード書いた!C#/Xamarinはいいぞ!
— ちょまど@MS入社して8ヶ月 (@chomado) 2016年12月8日
取り敢えず今日1番ハマったのはこれだった。Azure Storage の nugetが Xamarin .Forms の PCLに対応してなかったことの対応https://t.co/XlV0ZVCiw4
つまり、プラットフォーム固有機能を呼ぶときと同じ対応でOKということですね。
Prism.Formsでプラットフォーム固有処理を呼び出す方法はDependencyService
を使うかIPlatformInitializer
を使う方法の2通りがあります。
特に理由がない限りは(例えば既存でDependencyService
でガッツリ作ってるとか。まぁそれでも移行は楽ちんだからやった方がいいと思うけど)IPlatformInitializer
を使うのがいいでしょう。柔軟ですし、早いですし。
ということで対応方法のステップ。
ステップ1
PCLのプロジェクトにインターフェースを切る。
public interface IHogeService { Task<Hoge> HogeAsync(); }
ステップ2
NuGetからAndroidとiOSプロジェクトにライブラリを追加する。
ステップ3
AndroidかiOSプロジェクトのどちらかに、PCLに定義したインターフェースの実装を定義する。
public class HogeService : IHogeService { public Task<Hoge> HogeAsync() { // ライブラリを使ったコード } }
ステップ4
もう一方のプロジェクト(Androidにステップ3で実装したならiOS、iOSに実装したならAndroid)にリンクとしてステップ3で作ったファイルを追加。
これでソースコードの共有化を行います。
ステップ5
各プラットフォームのIPlatformInitializer
の実装にサービスの登録を行う。Prism Template Packを使ってる場合は自動的にMainActivity
とAppDelegate
に追加されています。
container.RegisterType<IHogeService, HogeService>(new ContainerControledLifetimeManager());
ステップ6
PCLで使いましょう。 ViewModelとかのコンストラクタにサービスを受け取るようにすることで、Androidで実行されたときはAndroid用のクラスが、iOSで実行されたときはiOS用のクラスがインジェクションされます。
まとめ
普通PCLか.NET Standard対応してるだろJKと思ってても、思わぬところで罠があったりするので頭の片隅に入れておきましょう。