かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Xamarin.FormsでPrism.Formsを使ってPCLに非対応なライブラリを使う方法

例えばMicrosoft.AzureのStorageのライブラリなんかがXamarin.AndroidとXamarin.iOSには対応してるけどPCLには対応してないといった感じです。

被害者がここに。

対応方法

ということで対応方法ですが、id:chomadoさんがちゃんと対応してました。

つまり、プラットフォーム固有機能を呼ぶときと同じ対応でOKということですね。

Prism.Formsでプラットフォーム固有処理を呼び出す方法はDependencyServiceを使うかIPlatformInitializerを使う方法の2通りがあります。

www.nuits.jp

特に理由がない限りは(例えば既存で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を使ってる場合は自動的にMainActivityAppDelegateに追加されています。

container.RegisterType<IHogeService, HogeService>(new ContainerControledLifetimeManager());

ステップ6

PCLで使いましょう。 ViewModelとかのコンストラクタにサービスを受け取るようにすることで、Androidで実行されたときはAndroid用のクラスが、iOSで実行されたときはiOS用のクラスがインジェクションされます。

まとめ

普通PCLか.NET Standard対応してるだろJKと思ってても、思わぬところで罠があったりするので頭の片隅に入れておきましょう。