PCL (Portable Class Library) – Xamarin 3 の新しいコード共有テクニック : XLsoft エクセルソフト
http://www.xlsoft.com/jp/products/xamarin/portable_class_libraries.html
Xamarinと、ポータブル・クラス・ライブラリ(PCL) – Build Insider
http://www.buildinsider.net/mobile/insidexamarin/13
Xamarin.iOS/Android に対応している Profile78 とは何か? | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6137
ひとまず、ポータブルクラスライブラリで作っておけば、Xamarin.iOS/Android 間で共有できる訳ですが、Windows Store App や Windows Phone 8.1 を含めるとややこしいわけで、それなりに取捨選択しないといけません。
が、PCL 作成時に対象のフレームワークを選択せねばならず、将来的な未知のフレームワークにはどう対応するのか?という問題もあり、田淵@XLsoft さんの記事にある通り、プラットフォーム依存する場合には Dependency Injection などを使ってうまく吸収してやらねばいけません。と言いますか、
- プラットフォーム依存しない部分を、PCL で書いて、TDD する。
- 機種依存/プラットフォーム依存する場合は、各コードで書く(場合によっては Objective-C とか)
- つなぎの部分を Interface/DI する。
ってな感じの地味な作業がベターかなと今は思ってます。作業量中心に考えて、それぞれのアプリ作成の状況に最適化、ってところですね。プラットフォーム毎のコードに苦労するのであれば、Xamarin.Forms などを使うメリットが低くなってしまうということです。
Reflection を使って、プラットフォームの差分を吸収しようかと思ったのですが、Xamarin.Android/iOS 自身が取っている TypeForwardedToAttribute を使うのもいいかもしれないと考えつつありますが。
■既存のプロファイルを調べる
というわけで、新しいプラットフォームに対応しようとすると、新しいプロファイルに対応しないといけません。それぞれのプラットフォームの組み合わせによって「Profile999」な感じで番号が振ってあるという大混乱ぶりなのですが、ソースコードが github などにアップされていれば(あるいは社内で持っていれば)プロファイルを切り替えてリビルドすれば ok です。
が、ソースコードのプロジェクトがあればよいのですが、DLL しかない状態に陥ると「これは、どのプロファイルなのか?」ってのが問題になる…と思いますよね。DLL を Visual Studio に参照設定しようとすると「異なるプロファイルなので、追加できません」とエラーが出るですが、果たして、その DLL は何のプロファイルなのか?
PCL の DLL をバイナリエディタで覗いてみると、プロファイルが書いてあります。これをバイナリで検索してもよいのですが、Assembly.LoadFile した後に、CustomAttributes コレクションの中身を探ってやれば見つかります。型が System.Runtime.Versioning.TargetFrameworkAttribute なものが見つかるので、そこに、”.NETPortable,Version=v4.5,Profile=Profile7″ な書式で書かれています。
■プロファイル名を抽出するツール
https://github.com/moonmile/CheckPCLProfile に、プロファイル名と、対応するプラットフォームを表示させるツールを公開しました。
コマンドラインで PCL の DLL を渡すと、プロファイ名が出てきます。たぶん、PCL 以外の DLL を渡すと落ちます。
AssemblyResolve で動的に DLL を読み込ませているのは FSharp.Core.dll のためです。どうやら、F# で作った PCL は CustomAttributes コレクションを探索するときに FSharp.Core を使うみたいですね。大抵の場合、PCL の DLL と同じ場所に FSharp.Core.dll があるので、それも一緒に読み込ませています。
■プロファイル名を直接書き換えると、別プロファイルで読み込めるのか?
実は、これが本題で作ったツールです。バイナリに「Profile7」と書かれている訳だから、「Profile78」と書き換えてしまえば、疑似的に対応する DLL が作れるのではないか?ってことです。名前が長くなってしまうので、文字列長あたりを直さないと駄目なんでしょうが、これを焼てみると…
結論は、だめでした。Assembly.Load 時に例外が発生して落ちてしまいますね。どうせ、制限されたクラスやメソッドしか使っていないのであれば、プロファイル名だけを切り替えればいいような気もするのですが…まぁ、これはリビルドってことで。