ポータブル クラス ライブラリ (PCL)

ヒント

ポータブル クラス ライブラリ (PCL) は、最新バージョンの Visual Studio では非推奨と見なされます。 PCL は引き続き開き、編集、コンパイルできますが、新しいプロジェクトでは、.NET Standard ライブラリを使用して、より大きな API サーフェス領域にアクセスすることをお勧めします。

クロスプラットフォーム アプリケーションを構築する上で重要な要素は、さまざまなプラットフォーム固有のプロジェクト間でコードを共有できることです。 ただし、これは、異なるプラットフォームでは異なるサブセットの .NET 基本クラス ライブラリ (BCL) を使用することが多く、そのために実際には別の .NET Core ライブラリ プロファイルに構築されるため、複雑になります。 つまり、各プラットフォームでは、同じプロファイルを対象とするクラス ライブラリのみを使用できるため、プラットフォームごとに個別のクラス ライブラリ プロジェクトが必要であるように見えます。

この問題に対処するコード共有には、.NET Standard プロジェクト共有アセット プロジェクトポータブル クラス ライブラリ (PCL) プロジェクトの 3 つの主要な方法があります。

  • .NET Standard プロジェクトは、.NET コードを共有するための推奨されるアプローチです。.NET Standard プロジェクトと Xamarin の詳細を参照してください。
  • 共有アセット プロジェクトでは、1 つのファイル セットを使用し、ソリューション内でコードを共有するための迅速かつ簡単な方法を提供し、通常は条件付きコンパイル ディレクティブを使用して、それを使用するさまざまなプラットフォームのコード パスを指定します (詳細については、共有プロジェクトの記事を参照してください)。
  • PCL プロジェクトは、既知の BCL クラス/機能セットをサポートする特定のプロファイルを対象とします。 ただし、PCL の欠点は、プロファイル固有のコードを独自のライブラリに分離するために、多くの場合、追加のアーキテクチャ作業が必要になることです。

このページでは、特定のプロファイルを対象とする PCL プロジェクトを作成する方法について説明します。このプロジェクトは、複数のプラットフォーム固有のプロジェクトで参照できます。

ポータブル クラス ライブラリとは

アプリケーション プロジェクトまたはライブラリ プロジェクトを作成すると、作成される DLL は、作成対象の特定のプラットフォームで動作するように制限されます。 これにより、Windows アプリのアセンブリを記述してから、これを Xamarin.iOS および Xamarin.Android で再利用することはできません。

ただし、ポータブル クラス ライブラリを作成する場合は、コードを実行するプラットフォームの組み合わせを選択できます。 ポータブル クラス ライブラリを作成するときに行う互換性の選択は、ライブラリがサポートするプラットフォームを記述する "プロファイル" 識別子に変換されます。

次の表は、.NET プラットフォームによって異なる機能の一部を示しています。 特定のデバイスまたはプラットフォームで実行することが保証されている PCL アセンブリを作成するには、プロジェクトの作成時に必要なサポートを選択するだけです。

機能 .NET Framework UWP アプリ Silverlight Windows Phone Xamarin
コア Y
LINQ Y
IQueryable Y 7.5+
シリアル化 Y
データの注釈 4.0.3 以降 Y

Xamarin 列には、Xamarin.iOS と Xamarin.Android が Visual Studio に付属するすべてのプロファイルをサポートしているという事実が反映されています。作成するすべてのライブラリの機能の可用性は、サポート対象として選択した他のプラットフォームによってのみ制限されます。

これには、次の組み合わせのプロファイルが含まれます。

  • .NET 4 または .NET 4.5
  • Silverlight 5
  • Windows Phone 8
  • UWP アプリ

Microsoft の Web サイトでさまざまなプロファイルの機能の詳細を確認し、サポートされているフレームワーク情報やその他のメモを含む別のコミュニティ メンバーの PCL プロファイルの概要を確認できます。

メリット

  1. 一元化されたコード共有 – 他のライブラリやアプリケーションで使用できる 1 つのプロジェクトでコードを記述およびテストします。
  2. リファクタリング操作は、ソリューションに読み込まれるすべてのコード (ポータブル クラス ライブラリとプラットフォーム固有のプロジェクト) に影響します。
  3. PCL プロジェクトは、ソリューション内の他のプロジェクトから簡単に参照できます。また、他のユーザーがソリューションで参照できるように出力アセンブリを共有することもできます。

短所

  1. 同じポータブル クラス ライブラリが複数のアプリケーション間で共有されるため、プラットフォーム固有のライブラリを参照することはできません (例: Community.CsharpSqlite.WP7)。
  2. ポータブル クラス ライブラリのサブセットには、MonoTouch と Mono for Android (DllImport や System.IO.File など) の両方で使用できるクラスが含まれていない場合があります。

Note

ポータブル クラス ライブラリは、最新バージョンの Visual Studio で非推奨になりました。代わりに .NET Standard ライブラリをお勧めします。

プロバイダー パターンまたは依存関係の挿入を使用して、ポータブル クラス ライブラリで定義されているインターフェイスまたは基底クラスに対してプラットフォーム プロジェクトの実際の実装をコーディングする場合、両方の欠点がある程度回避できます。

次の図は、ポータブル クラス ライブラリを使用してコードを共有するものの、プラットフォームに依存する機能を渡すには依存関係の挿入も使用するクロスプラットフォーム アプリケーションのアーキテクチャを示します。

This diagram shows the architecture of a cross-platform application using a Portable Class Library to share code, but also using Dependency Injection to pass in platform-dependent features

Visual Studio for Mac のチュートリアル

このセクションでは、Visual Studio for Mac を使用してポータブル クラス ライブラリを作成して使用する方法について説明します。 完全な実装については、「PCL の例」セクションを参照してください。

PCL の作成

ポータブル クラス ライブラリをソリューションに追加するのは、通常のライブラリ プロジェクトを追加するのとよく似ています。

  1. [新しいプロジェクト] ダイアログで、[マルチプラットフォーム] >[ライブラリ] >[ポータブル ライブラリ] オプションを選択します。

    Create a new PCL project

  2. PCL が Visual Studio for Mac で作成されると、Xamarin.iOS および Xamarin.Android で動作するプロファイルを使用して自動的に構成されます。 次のスクリーンショットに示すように、PCL プロジェクトが表示されます。

    PCL project in the solution pad

これで、PCL でコードを追加する準備ができました。 また、他のプロジェクト (アプリケーション プロジェクト、ライブラリ プロジェクト、その他の PCL プロジェクト) でも参照できます。

PCL 設定の編集

このプロジェクトの PCL 設定を表示および変更するには、プロジェクトを右クリックし、[オプション] > [ビルド] > [全般] を選択して、ここに示す画面を表示します。

PCL Project Options to set the profile

[変更] をクリックして、このポータブル クラス ライブラリのターゲット プロファイルを変更します。

コードが既に PCL に追加された後にプロファイルが変更された場合、コードが新しく選択したプロファイルの一部でない機能を参照していると、ライブラリがコンパイルされなくなる可能性があります。

PCL の操作

コードが PCL ライブラリで記述されている場合、Visual Studio for Mac エディターは選択したプロファイルの制限を認識し、それに応じてオートコンプリート オプションを調整します。 たとえば、このスクリーンショットは、Visual Studio for Mac で使用されている既定のプロファイル (Profile136) を使用する System.IO のオートコンプリート オプションを示しています。ここで、使用可能なクラスの約半分が表示されていることを示すスクロール バーに注目してください (実際には使用可能なクラスは 14 個のみ)。

Intellisense list of 14 classes in the System.IO class of a PCL

これを、Xamarin.iOS または Xamarin.Android プロジェクトの System.IO オートコンプリートと比較します。PCL プロファイルに含まれていないクラスである FileDirectory など、一般的に使用されるクラスが 40 個あります。

Intellisense list of 40 classes in .NET Framework System.IO namespace

これには、PCL の使用に関して暗黙のトレードオフがあることを表しています。多くのプラットフォーム間でコードをシームレスに共有する機能は、使用可能でない特定の API もあることを意味します。これは、すべての可能なプラットフォームに対して API が同等の実装を持つわけではないからです。

PCL の使用

PCL プロジェクトが作成されたら、通常の参照を追加するのと同じ方法で、互換性のある任意のアプリケーションまたはライブラリ プロジェクトからそのプロジェクトへの参照を追加できます。 Visual Studio for Mac で、[参照] ノードを右クリックし、[参照の編集] を選択します。その後、次に示すように、[プロジェクト] タブに切り替えます。

Add a reference to a PCL via Edit References option

次のスクリーンショットは、TaskyPortable サンプル アプリのソリューション パッドを示しています。下部に PCL ライブラリが表示され、Xamarin.iOS プロジェクトでその PCL ライブラリへの参照が示されています。

TaskyPortable sample solution showing PCL project

PCL からの出力 (つまり、結果のアセンブリ DLL) は、ほとんどのプロジェクトへの参照として追加することもできます。 これにより、PCL はクロスプラットフォーム コンポーネントとライブラリを出荷するための理想的な方法になります。

PCL の例

TaskyPortable サンプル アプリケーションは、Xamarin でポータブル クラス ライブラリを使用する方法を示しています。 iOS と Android で実行されている結果のアプリのスクリーンショットを次に示します。

Here are some screenshots of the resulting apps running on iOS, Android and Windows Phone

これは、多数のデータと、純粋にポータブルなコードであるロジック クラスを共有し、SQLite データベース実装に依存関係の挿入を使用してプラットフォーム固有の要件を組み込む方法も示します。

ソリューションの構造を次に示します (それぞれ Visual Studio for Mac と Visual Studio)。

The solution structure is shown here in Visual Studio for Mac and Visual Studio respectively

SQLite-NET コードには、デモ目的でプラットフォーム固有の部分 (各異なるオペレーティング システム上の SQLite 実装を操作するため) があるため、ポータブル クラス ライブラリにコンパイルできる抽象クラスと、iOS および Android プロジェクトでサブクラスとして実装された実際のコードにリファクタリングされています。

TaskyPortableLibrary

ポータブル クラス ライブラリは、これがサポートできる .NET 機能では制限されています。 複数のプラットフォームで実行するようにコンパイルされているため、SQLite-NET で使用される [DllImport] 機能を利用することはできません。 代わりに、SQLite-NET は抽象クラスとして実装され、残りの共有コードを介して参照されます。 抽象 API の抽出を次に示します。

public abstract class SQLiteConnection : IDisposable {

    public string DatabasePath { get; private set; }
    public bool TimeExecution { get; set; }
    public bool Trace { get; set; }
    public SQLiteConnection(string databasePath) {
         DatabasePath = databasePath;
    }
    public abstract int CreateTable<T>();
    public abstract SQLiteCommand CreateCommand(string cmdText, params object[] ps);
    public abstract int Execute(string query, params object[] args);
    public abstract List<T> Query<T>(string query, params object[] args) where T : new();
    public abstract TableQuery<T> Table<T>() where T : new();
    public abstract T Get<T>(object pk) where T : new();
    public bool IsInTransaction { get; protected set; }
    public abstract void BeginTransaction();
    public abstract void Rollback();
    public abstract void Commit();
    public abstract void RunInTransaction(Action action);
    public abstract int Insert(object obj);
    public abstract int Update(object obj);
    public abstract int Delete<T>(T obj);

    public void Dispose()
    {
        Close();
    }
    public abstract void Close();

}

共有コードの残りの部分では、抽象クラスを使用してオブジェクトをデータベースに "格納"し、データベースから "取得" します。 この抽象クラスを使用するアプリケーションでは、実際のデータベース機能を提供する完全な実装を渡す必要があります。

TaskyAndroid および TaskyiOS

iOS および Android アプリケーション プロジェクトには、PCL で共有コードを接続するために使用されるユーザー インターフェイスやその他のプラットフォーム固有のコードが含まれています。

これらのプロジェクトには、そのプラットフォームで動作する抽象データベース API の実装も含まれています。 iOS および Android では、Sqlite データベース エンジンはオペレーティング システムに組み込まれているため、実装は、データベース接続の具体的な実装を提供するために、示されているように [DllImport] を使用できます。 プラットフォーム固有の実装コードの抜粋を次に示します。

[DllImport("sqlite3", EntryPoint = "sqlite3_open")]
public static extern Result Open(string filename, out IntPtr db);

[DllImport("sqlite3", EntryPoint = "sqlite3_close")]
public static extern Result Close(IntPtr db);

完全な実装は、サンプル コードで確認できます。

まとめ

この記事では、ポータブル クラス ライブラリの利点と欠点について簡単に説明し、Visual Studio for Mac と Visual Studio 内から PCL を作成して使用する方法を示し、最後に、PCL の動作を示す完全なサンプル アプリケーション (TaskyPortable) を導入しました。