酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Windowsストアアプリで使えるポータルクラスライブラリ(Portable Class Library/PCL)について

サーバーサイドでの「ASP.NET」からスマートウォッチと呼ばれる腕時計などの組み込み機器向けの「.NET Micro Framework」まで、あらゆる分野で.NET Frameworkや各デバイス向けにカスタマイズされた.NET Frameworkのサブセットが存在しています。

.NET Frameworkのテクノロジーを使ってアプリの開発が可能なプラットフォームがこの2,3年で急激に拡大しています。もっとも勢いがあるのはタブレットアプリとスマートフォンアプリの分野でしょう。マイクロソフト社自身がデバイスと開発環境を提供する「Windowsストアアプリ」、「Windows Phone」はその筆頭です。

そして、.NET Framework互換のフレームワークである「Mono」から派生したXamain社のスマートフォンプロダクト「Xamarin.Android」「Xamarin.iOS」が勢いを後押ししています。2012年9月には、マイクロソフト社はXamarin社と提携を発表し、C#を使ったスマートフォンアプリ開発を強化しています。

さて、デスクトップWindowsやWindowsストアアプリ、Windows Phoneなどの様々なプラットフォームでのアプリ開発にVB.NETやC#を使うことができるようになったというのは前述した通りです。開発に使うプログラミング言語を統一することができれば、マルチプラットフォームを対象にして同一タイトルのアプリやゲームを提供することになった場合、プラットフォームに依存しない処理に関してはソースコードを共有することが可能です。

とある機能をひとつ追加しようとすると、通常、設計・実装・テストのフェーズを経て、プロダクトに組み込まれます。それぞれのフェーズでコストが掛かりますが、それを複数のプラットフォームで対応しなければいけないとなればその分だけコストが掛かってきます。

可能な限り開発や保守を効率化するためにコードを最大限に「再利用」しようとします。「最大限再利用する」というのはどういうことかというと、「最大限」の解釈は多々あるかと思いますが、1回実装して1回テストしたコードが複数のプラットフォームで使えるということではないでしょうか。現時点での最大限再利用したいという問いの解のひとつに「ポータブルクラスライブラリ(Portable Class Library)」があります。

例えば、デスクトップWindows向けアプリでの処理とWindowsストアアプリとロジックを共有したいという要望があったとします。これらのコードを書くコストを抑えるためにはどうしたらよいでしょうか。

本記事では、ソースコードの共有方法についていくつか紹介したのち、ポータブルクラスライブラリを使ったマルチプラットフォームでソースコードの共有方法について紹介します。

プラットフォームごとにコードを実装する

それぞれのプラットフォームに最適化されたロジックを実装します。 この手段を使ってコードの共有をする場合は、実際に別々のプラットフォームで同じコードをフルスクラッチで実装するケースは少ないと思われます。プロジェクトAとプロジェクトBがあり、プロジェクトAが開発したソースコードをプロジェクトBで取り込む場合に使われるのではないかと思います。

よくあるケースとしては、デスクトップWindows向けのアプリで実装していたコードを流用しようとWindowsストアアプリにソースファイルをコピー&ペーストする場合です。

f:id:ch3cooh393:20140422152422j:plain

Windowsストアアプリ側でソースファイルを取り込んでしまってから、新規にデスクトップWindowsアプリに追加したクラスやメソッドを取り込みたい場合、手動で取り込まないといけないデメリットがありますが、これは片一方での修正や変更に影響されないメリットにもなります。

完全に同じロジックを使用するのであれば、後述する[リンクとして追加]によるソースファイルの共有や、ポータブルクラスライブラリプロジェクトの共有をすべきでしょう。

[リンクとして追加]によるソースコード共有

2つのプロジェクトからそれぞれ同じ1つのソースファイルを共有します。 [リンクとして追加]によるソースコードの共有は、.NET Frameworkを使った開発でスタンダードなソースコードの共有方法のひとつです。Visual Studioでファイルを追加する際に、[リンクとして追加]を選択してファイルを参照して、1つのファイルを複数のプロジェクトで共有します。

下図は「[リンクとして追加]によるソースコード共有」を示したイメージ図です。

f:id:ch3cooh393:20140422152429j:plain

この方法でソースコードの共有をおこなうメリットとしては、それぞれのプラットフォームに依存している一部分のロジック以外は同じコードで良いところです。プラットフォームに依存するコードは、#if 〜 #endif を使って切り分けます。

f:id:ch3cooh393:20140424221921j:plain

例えば、アプリの設定値を保存することを考えてみましょう。開発の対象はWindowsストアアプリとWindows Phoneアプリです。

プラットフォームに依存するコードは、#if 〜 #endif を使って切り分けます。 適当にテンプレートを使ってプロジェクトを作ってみました。プロジェクトのプロパティを見てみましょう。

Windowsストアアプリでは「NETFX_CORE」となっていることが確認できますWindows Phoneの場合は「WINDOWS_PHONE」となっています。

Windowsストアアプリでは、アプリの設定値の保存にはWindows.Storage名前空間の「ApplicationData.Current.LocalSettingsクラス」を使用します。SilverlightやWindows Phone (Silverlight)アプリにはLocalSettingsクラスが存在していないので、代わりにSystem.IO.IsolatedStorage名前空間の「IsolatedStorageSettings.ApplicationSettingsプロパティ」を使用します。

さてどのようなコードになるでしょうか。Settingsクラスを作ってみました。まず名前空間が異なるなるため、usingディレクティブで省略する名前空間を #if NETFX_COREで使い分けしています。

#if NETFX_CORE && !WINDOWS_PHONE
using Windows.Storage;
#elif WINDOWS_PHONE
using System.IO.IsolatedStorage;
#endif

public static class Settings
{
  public static void Set<T>(string key, T value)
  {
#if NETFX_CORE && !WINDOWS_PHONE
    ApplicationData.Current.LocalSettings.Values[key] = value;
#elif WINDOWS_PHONE
    IsolatedStorageSettings.ApplicationSettings[key] = value;
    IsolatedStorageSettings.ApplicationSettings.Save();
#endif
  }
}

前述したソースコードではファイルにアクセスするロジックがあったため、[リンクとして追加]によるソースコードの共有するのが最適でした。

もし共有したいソースコードが、プラットフォームで使用可能な.NET Framework APIのサブセットで記述されているのであれば、共有したいロジックを後述する「ポータブルクラスライブラリ」にまとめてしまって、そのプロジェクトを共有するのが良いでしょう。

ポータルクラスライブラリによるプロジェクト共有

ポータブルクラスライブラリとは、.NET Framework 4.0から利用できるようになった機能でデスクトップWindows、Windowsストアアプリ、Windows Phone、Xbox 360向けアプリ/ゲームから利用することができる「ポータブルクラスライブラリ」を作成できます。

ポータブルクラスライブラリのアセンブリは、プロジェクトの作成時または開発中にアセンブリを利用する側のプラットフォーム(ターゲットと呼ばれる)を選択します。選択されたターゲットのサブセットが自動的にサポートされます。

ポータブルクラスライブラリを使用することができるプラットフォームは下表の通りです。Visual Studio 2013 Update2にてポータブルクラスライブラリのプロジェクトを新規に作成した場合にデフォルトで選択されているターゲットの横に(*)を付けています。

f:id:ch3cooh393:20160115151403p:plain

Visual Studio 2012では選択できた「Xbox 360」が、Visual Studio 2013のポータルブルクラスライブラリの一覧からが削除されています。Xamarin Studioがインストールされていると「Xamarin.Android」と「Xamarin.iOS」が追加されます。

Visual Studio 2012 Pro以上のバージョンで、プロジェクト作成時にウィザードからテンプレートを選択することが可能です。

f:id:ch3cooh393:20140422155447j:plain

参照