デスクトップ アプリの移植ガイダンス

ほとんどのアプリケーション コードは、次のいずれかの領域に分類できます。

  • ユーザー インターフェイス コード (ウィンドウやボタンなど)
  • サード パーティ コントロール (グラフなど)
  • ビジネス ロジック (検証ルールなど)
  • ローカル データのストレージとアクセス
  • Web サービスとリモート データ アクセス

C# (または Visual Basic.NET) で記述された Windows フォームおよび WPF アプリケーションの場合、ビジネス ロジック、ローカル データ アクセス、Web サービス コードの驚くべき量をプラットフォーム間で共有できます。

.NET Portability Analyzer

Visual Studio 2017 以降では、既存のアプリケーションを調べて、他のプラットフォームに "そのまま" 移植できるコードの量を示す .NET Portability Analyzer (Windows 版のダウンロード) がサポートされています。

GitHub の Portability Analyzer をダウンロードして同じレポートを提供するために使用できるコマンドライン ツールもあります。

"x% のコードを移植できます。 次は何をしますか?"

アナライザーでコードの大きな部分が移植可能と示される可能性がありますが、どのようなアプリにも他のプラットフォームに移動できない部分が確実に存在します。

コードのさまざまなチャンクは、おそらく次のいずれかに分類されます。これらについては後で詳しく説明します。

  • 再利用できる移植可能なコード
  • 変更を必要とするコード
  • 移植できず、書き直しが必要なコード

再利用できる移植可能なコード

すべてのプラットフォームで使用できる API に対して記述された .NET コードは、変更せずにクロスプラットフォームにできます。 理想的には、このコードをすべてポータブル クラス ライブラリ、共有ライブラリ、または .NET 標準ライブラリに移動し、既存のアプリ内でそれをテストできます。

その共有ライブラリを、他のプラットフォーム (Android、iOS、macOS など) のアプリケーション プロジェクトに追加できます。

変更を必要とするコード

一部の .NET API は、すべてのプラットフォームでは使用できない場合があります。 このような API がコードに存在する場合、クロスプラットフォーム API を使うには、それらのセクションを書き直す必要があります。

そのようなものの使用例であるリフレクション API は、.NET 4.6 では使用できますが、すべてのプラットフォームで使用できるわけではありません。

移植可能な API を使ってコードを書き直したら、そのコードを共有ライブラリにパッケージ化して、既存のアプリ内でテストできるはずです。

移植できず、書き直しが必要なコード

おそらくクロスプラットフォームにできないコードの例を次に示します。

  • ユーザー インターフェイス - Windows フォームまたは WPF の画面は、たとえば Android や iOS のプロジェクトでは使用できません。 このコントロールの比較を参考にして、ユーザー インターフェイスを書き直す必要があります。

  • プラットフォーム固有のストレージ - プラットフォーム固有のテクノロジ (ローカル SQL Server Express データベースなど) に依存するコード。 これは、クロスプラットフォームの代替手段 (データベース エンジン用の SQLite など) を使って書き直す必要があります。 UWP には Android や iOS と若干異なる API があるため (たとえば、大文字と小文字が区別されるファイル システムと、されないファイル システム)、一部のファイル システム操作も調整が必要な場合があります。

  • サード パーティ製コンポーネント – アプリケーションのサード パーティ製コンポーネントが他のプラットフォームで使用できるかどうかを確認します。 ビジュアルではない NuGet パッケージのように利用できるものもありますが、他のものはできません (特に、グラフなどのビジュアル コントロールやメディア プレーヤー)

コードを移植可能にするためのヒント

  • 依存関係の挿入 – プラットフォームごとに異なる実装を提供します。

  • 階層型アプローチ – MVVM、MVC、MVP、または移植可能なコードをプラットフォーム固有のコードから分離するのに役立つその他のパターンかどうか。

  • メッセージング – コードを渡すメッセージを使って、アプリケーションの異なる部分の間の相互作用を切り離すことができます。