Windows PhoneアプリでF#を使う

この記事はWindows Phone Advent Calendar 2014の20日目の記事です。

さて「F#で2ch専用ブラウザをつくろう」では「2ちゃんねる」の掲示板データを読みこむためのライブラリをF#で記述しました。今回はこのライブラリをWindows Phoneアプリの開発から使えるようにしてみます。Windows PhoneアプリにはSilverlightアプリとユニバーサルアプリの2種類がありますが、ここではもちろんユニバーサルアプリを対象にしています。

F#でPortable Class Libraryを作る

F#のコードをユニバーサルアプリから使う基本的な流れは以下のようになります。

  1. F#のコードをPortable Class Library (PCL)の形でコンパイルしておく
  2. PCLのアセンブリをユニバーサルアプリのプロジェクトから参照する

PCLを作るにはプロジェクトの新規作成からPortable Libraryを選びます。このプロジェクトテンプレートで生成されるクラスライブラリは.NET 4.5ベースのPCLを生成します。

とりあえず、プロジェクトを生成して、前回作成したコードをインポートしてみます。これで完了!と書きたいところなのですが、実はこのライブラリ、このままでは使えません。

「2ちゃんねる」APIの解説で少し触れましたが、掲示板データのやりとりはShift JISで行います。ところがWindows Phone上のWindows Runtimeではこのエンコーディングはサポートされていないため、Encoding.GetEncoding(“SJIS”)を呼び出した時点で例外が発生してしまうのです。

Shift JISがWindows Phone上のランタイムでサポートされていないのはWindows Phone 7時代からの話なので、実は改めて驚くことはないのですが、PCLでコンパイルが通ったからといって実行できるとは限らない典型例といえます。自分でなんとか実装するしかないのですが、幸い @kazuakix さんによる SJIS Encoding の実装例があるので、そちらを参考にすることにしましょう。

まずはWin32 APIの関数であるMultiByteToWideCharを呼び出すためにWindows Runtimeコンポーネント(SjisEncoding)を定義します。

次にこれをEncodingクラスとして利用できるようにSjisEncodingクラスを定義します。


さて、記事にしたがってエンコーディングのクラスを書いてみたのですが、これをF#のコードから使うのにはもうひと工夫必要だったりします。というのも、F#のPCLから参照できるのはPCLのライブラリのみなのですが、このSjisEncodingをPCLのライブラリとしてコンパイルすることはできません。というのもWin32のAPIを呼び出す部分がWinRTコンポーネントになっており、これをPCLから参照することはできないからです。

そこでMonalith.Communicationモジュールから直接このクラスを参照するのではなく、外部からEncodingのインスタンスを受け取るようにして、Monalith.Communicationからユニバーサルアプリプロジェクトへの参照をなくします。

モジュールとして定義していたHttpClientをクラスとして定義しなおし、Encodingをコンストラクタの引数として受け取るように変更しています。とりあえず、これでWindows Phoneアプリの開発にも使えるPCLとして形なりました。

明日のWindows Phone Advent Calendar 2014 21日目の記事は @karno さんです.

謝辞:快く参照を許可してくれた@kazuakixさん、ありがとうございました。あと、はやくSurface Pro 3買ってください!