質問: 困っていること -------- Xamarin.Forms(PCL)でWCFアクセスを行う場合のプロジェクト構成を、どうすべきかわからず困っています。 **(ここではWCFを問題にしていますが、これに限った話ではなく、プロファイルによるAPIの制限のため必要なクラスが呼べないという問題です。)** 詳細 --- (前提:ここでは、ソリューション内に ViewModelプロジェクト(PCL)、Androidプロジェクト、iOSプロジェクトが存在するとしてください。) (また、ソリューションのベースはPrism Template Packを使用して作成しています。) 以下のページを参考に、XamarinのソリューションからWCFアクセスを行う処理を作成しています。 Walkthrough - Working with WCF この解説では、ソリューション内で * `System.Runtime.Serialization`, `System.ServiceModel`, `System.ServiceModel.Web` をAndroidプロジェクトの参照に追加 * `HelloWorldService.cs` をAndroidプロジェクトに作成 * `System.Runtime.Serialization`, `System.ServiceModel`, `System.ServiceModel.Web` をiOSプロジェクトの参照に追加 * `HelloWorldService.cs`(Androidプロジェクトに置いたファイルのコピー) をiOSプロジェクトに作成 ということをしています。 ここで問題があります。 それは、ViewModel プロジェクトで `HelloWorldService.cs` に定義されたクラスを使用できないことです。 (通常はViewModelからAndroid/iOSプロジェクトを参照することはしないと思っています) `HelloWorldService`の中では、`System.Runtime.Serialization`, `System.ServiceModel`, `System.ServiceModel.Web` を使用しています。 (プロファイルにもよるかもしれませんが)PCL(ViewModel)からは `System.Runtime.Serialization`, `System.ServiceModel`, `System.ServiceModel.Web` を呼ぶことができません。 ですから、仕方なく `HelloWorldService`をAndroid/iOSプロジェクトに配置しているのだろうと思います。 `HelloWorldService.cs`の中には通常複数のクラスが定義されており、そのクラスの一部をPCL(ViewModel)で使いたいという要求があります。 (例えばクライアント-サーバ間のデータのやりとりに使用する複雑なクラスが定義されており、これをViewModelで再定義するのは避けたいです) しかしながらPCLから`HelloWorldService`を参照することができないため困っています。 このような問題を解決する良い方法はないでしょうか。 (そもそも、内容が全く同じHelloWorldService.csを2つ用意する、という時点で気持ち悪さがあります。) ### 追記 ちなみに、プロファイルの制限がきついからViewModelからSystem.ServiceModelなどが参照できないのでは?と思い、プロジェクトのターゲット設定で「ASP.NET Core 1.0」を外してみたところ、 ``` 型 'Object' は、参照されていないアセンブリに定義されています。アセンブリ 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' に参照を追加する必要があります。 ``` というエラーが、Prismが使われているクラスのあちこちで発生するようになってしまいました。 (例えばViewModelのファイルで `public class MainPageViewModel : BindableBase, INavigationAware` ← BindableBase の部分でエラーが出ます)
回答: > > (ここではWCFを問題にしていますが、これに限った話ではなく、プロファイルによるAPIの制限のため必要なクラスが呼べないという問題です。) > > > .NET Framework, Xamarin.Android(MonoDroid), Xamarin.iOS(MonoTouch) それぞれで同じクラスが用意されていても、PCL のプロファイルでそのクラスが定義されていなければ使用できない(=プラットフォーム固有のAndroidやiOSプロジェクト側での実装が必要になる)のは仕方のないことだと考えます。 ので、Xamarinに限らず.NET系での「複数プラットフォームに対応するライブラリ」は、PCLだけで完結できることは少なく、プラットフォーム固有の実装を含んだライブラリと共に利用されるのが一般的という認識です。 Plugins for Xamarin は、PCL+プラットフォーム固有のライブラリの組み合わせで作られているライブラリ群です。 考え方は、PCLプロジェクトでは、アプリケーションから使用されるAPIのインターフェースを定義し、そのインターフェースにAndroidプロジェクトやiOSプロジェクトにあるプラットフォーム固有の実装を「注入」します。 広義には DI(Dependency Injection=依存性の注入) と呼ばれるものですが、Plugins for Xamarin では「Bait & switch」というテクニックを使用してこれを実現しています。 その仕組みは、 * Plugins for Xamarinを作ろう! - ぴーさんログ * 共有コードからネイティブ依存処理が使える!PCLを使ったXamarinライブラリ作成テクニック (フェンリル | デベロッパーズブログ) で解説されています。 > > そもそも、内容が全く同じHelloWorldService.csを2つ用意する、という時点で気持ち悪さがあります。 > > > これも同様の理由で仕方のないことと考えますが、Visual Studio のソースコードのリンク機能などでごまかすことはできるかと思います。