WPF アドインの概要

.NET Framework には、アドイン機能拡張をサポートするアプリケーションの作成に使用できるアドイン モデルが用意されています。 このアドイン モデルを使用することで、アプリケーション機能に統合され、アプリケーション機能を拡張するアドインを作成できます。 一部のシナリオでは、アドインが提供する UIs をアプリケーションで表示する必要があります。 このトピックでは、WPF が .NET Framework アドイン モデルを強化してこうしたシナリオを実現するしくみ、背後にあるアーキテクチャ、その利点、および制限事項について説明します。

このトピックは、次のセクションで構成されています。

  • 必要条件
  • アドインの概要
  • .NET Framework アドイン モデルの概要
  • WPF アドイン
  • ユーザー インターフェイスを返すアドイン
  • ユーザー インターフェイスであるアドイン
  • 複数の UI を返すアドイン
  • アドインと XAML ブラウザー アプリケーション
  • WPF アドイン アーキテクチャ
  • WPF アドインの利点
  • WPF アドインの制約
  • パフォーマンスの最適化
  • 関連トピック

必要条件

.NET Framework アドイン モデルを十分に理解していることが必要です。 詳細については、「アドインおよび拡張機能」を参照してください。

アドインの概要

新しい機能を追加するためにアプリケーションを再コンパイルして再配置する手間を省くことを目的として、アプリケーションは機能拡張メカニズムを実装し、開発者 (開発元、サード パーティのいずれも) が元のアプリケーションに統合される別のアプリケーションを作成できるようにしています。 こうした拡張機能をサポートする方法としては、アドイン ("アドオン"、"プラグイン" などとも呼ばれる) の使用が最も一般的です。 アドインによる機能拡張を実行する実際のアプリケーションとして、次のようなものが挙げられます。

  • Internet Explorer のアドオン。

  • Windows Media Player のプラグイン。

  • Visual Studio のアドイン。

たとえば、Windows Media Player のアドイン モデルにおいて、サード パーティの開発者は、Windows Media Player の機能をさまざまな形で拡張する "プラグイン" を実装できます。たとえば、Windows Media Player でネイティブ サポートされていないメディア形式 (DVD、MP3 など) のデコーダーおよびエンコーダー、オーディオ エフェクト、スキンなどを作成できます。 各アドイン モデルは、アプリケーション固有の機能を組み込むために構築されますが、どのアドイン モデルにも共通するエンティティや動作がいくつかあります。

典型的な機能拡張ソリューションの主な 3 つのエンティティは、コントラクト、アドイン、およびホスト アプリケーションです。 コントラクトは、次の 2 つの方法で、アドインとホスト アプリケーションとの統合方法を定義します。

  • アドインはホスト アプリケーションによって実装される機能と一体化します。

  • ホスト アプリケーションはアドインが一体化するための機能を公開します。

アドインを使用できるようにするためには、ホスト アプリケーションが実行時にアドインを検索して読み込む必要があります。 したがって、アドインをサポートするアプリケーションには次の機能が必要です。

  • 探索 : ホスト アプリケーションによってサポートされるコントラクトに準拠しているアドインを検索します。

  • アクティブ化 : アドインを読み込んで実行し、アドインとの通信を確立します。

  • 分離 : アプリケーション ドメインまたはアプリケーション プロセスを使用することで他から切り離すための境界を確立し、アドインの使用に伴うセキュリティおよび実行に関する潜在的な問題からアプリケーションを保護します。

  • 通信 : アドインとホスト アプリケーションが分離の境界を越えて通信し、メソッドを呼び出したりデータを渡したりできるようにします。

  • 有効期間管理 : アプリケーション ドメインとアプリケーション プロセスの読み込みおよびアンロードを、クリーンで予測可能な方法で行います (「アプリケーション ドメイン」を参照)。

  • バージョン管理 : ホスト アプリケーションとアドインのどちらかに、新バージョンが作成された後も引き続き通信できるようにします。

このことからわかるように、堅牢なアドイン モデルの開発は簡単なことではありません。 そのため、.NET Framework にはアドイン モデルの構築に必要なインフラストラクチャが用意されています。

メモメモ

アドインの詳細については、「アドインおよび拡張機能」を参照してください。

.NET Framework アドイン モデルの概要

.NET Framework アドイン モデルは、System.AddIn 名前空間にあり、アドイン機能拡張の開発を単純化するために設計された型のセットが用意されています。 .NET Framework アドイン モデルの基本単位はコントラクトです。コントラクトは、ホスト アプリケーションとアドイン間の通信を定義します。 コントラクトのホスト アプリケーション固有のビューを使用して、コントラクトはホスト アプリケーションに公開されます。 同様に、コントラクトのアドイン固有のビューがアドインに公開されます。 アダプターは、ホスト アプリケーションとアドインが、コントラクトの対応するビュー間で通信するために使用されます。 コントラクト、ビュー、およびアダプターはセグメントと見なされ、関連セグメントのセットがパイプラインを構成します。 .NET Framework アドイン モデルはパイプラインを基盤とし、それを基に探索、アクティブ化、セキュリティ分離、実行分離 (アプリケーションのドメインとプロセスを両方使用)、通信、有効期間管理、およびバージョン管理をサポートします。

このサポート全体を使用して、開発者はホスト アプリケーションの機能を統合するアドインを開発できます。 ただし、一部のシナリオでは、アドインが提供する UIs をホスト アプリケーションで表示する必要が生じます。 .NET Framework の各プレゼンテーション テクノロジには UIs 実装の独自のモデルがあるため、.NET Framework アドイン モデルは特定のプレゼンテーション テクノロジをサポートしません。 その代わり、WPF では .NET Framework アドイン モデルをアドインの UI サポートという形で機能拡張します。

WPF アドイン

WPF を .NET Framework アドイン モデルと併用することで、ホスト アプリケーションでアドインの UIs を表示する必要があるさまざまなシナリオに対応できます。 特に、WPF によるこれらのシナリオの対応には、次の 2 つのプログラミング モデルが使用されます。

  1. アドインが UI を返す。 アドインが、コントラクトの定義に従って、メソッド呼び出しを介してホスト アプリケーションに UI を返します。 このシナリオは、次の場合に使用されます。

    • アドインが返す UI の外観が、動的に生成されるレポートなど、実行時にしか存在しないデータまたは条件に依存している。

    • アドインが提供するサービスの UI が、そのアドインを使用できるホスト アプリケーションの UI と違っている。

    • アドインは主にホスト アプリケーション向けのサービスを実行し、UI を使用してホスト アプリケーションにステータスをレポートする。

  2. アドインが UI である。 アドインが、コントラクトの定義に従う UI です。 このシナリオは、次の場合に使用されます。

    • アドインは表示以外のサービス (アドバタイズメントなど) を提供しない。

    • アドインが提供するサービスの UI は、そのアドインを使用できるすべてのホスト アプリケーションで共通である (電卓、カラー ピッカーなど)。

これらのシナリオでは、UI オブジェクトをホスト アプリケーション ドメインとアドイン アプリケーション ドメインとの間で受け渡しできる必要があります。 .NET Framework アドイン モデルは、アプリケーション ドメイン間の通信においてリモート処理に依存しているため、それらの間で受け渡しされるオブジェクトはリモート処理可能である必要があります。

リモート処理可能なオブジェクトとは、次の 1 つ以上に該当するクラスのインスタンスです。

メモメモ

リモート処理可能な .NET Framework オブジェクトの作成の詳細については、「Making Objects Remotable」を参照してください。

WPF UI の型はリモート処理可能ではありません。 この問題を解決するため、WPF は .NET Framework アドイン モデルを拡張して、アドインによって作成される WPF UI をホスト アプリケーションで表示できるようにします。 これは WPF によって、INativeHandleContract インターフェイスと、FrameworkElementAdapters クラスの 2 つの静的メソッド ContractToViewAdapter および ViewToContractAdapter という 2 つの方法でサポートされています。 大まかに、これらの型およびメソッドは次のように使用されます。

  1. WPF では、アドインが提供する UIs が、図形、コントロール、ユーザー コントロール、レイアウト パネル、ページなど、FrameworkElement から直接または間接的に派生したクラスである必要があります。

  2. UI がアドインとホスト アプリケーションとの間で受け渡しされることをコントラクトで宣言する場合、必ず INativeHandleContract として宣言する必要があります (FrameworkElement ではない)。INativeHandleContract はアドイン UI のリモート処理可能な表現で、分離の境界を越えて受け渡しできます。

  3. アドインのアプリケーション ドメインから渡される前に、FrameworkElement は、ViewToContractAdapter 呼び出しによって、INativeHandleContract としてパッケージ化されます。

  4. ホスト アプリケーションのアプリケーション ドメインに渡された後、INativeHandleContract は、ContractToViewAdapter 呼び出しによって、FrameworkElement として再パッケージ化する必要があります。

INativeHandleContractContractToViewAdapter、および ViewToContractAdapter の使用形態は、個々のシナリオによって異なります。 以降では、各プログラミング モデルについて詳しく説明していきます。

ユーザー インターフェイスを返すアドイン

アドインが UI をホスト アプリケーションに返すようにするには、次のことが必要です。

  1. ホスト アプリケーション、アドイン、およびパイプラインが、.NET Framework の「アドインおよび拡張機能」の説明に従って作成されている必要があります。

  2. コントラクトに IContract を実装することが必要です。また、UI を返すようにするため、戻り値が INativeHandleContract 型であるメソッドをコントラクトで宣言する必要があります。

  3. アドインとホスト アプリケーションとの間で受け渡される UI は、直接または間接的に、FrameworkElement から派生している必要があります。

  4. アドインが返す UI は、分離境界を越える前に、FrameworkElement から INativeHandleContract に変換される必要があります。

  5. 返される UI は、分離境界を越えた後に、INativeHandleContract から FrameworkElement に変換される必要があります。

  6. ホスト アプリケーションは、返された FrameworkElement を表示します。

UI を返すアドインを実装する方法の例については、「方法 : UI を返すアドインを作成する」を参照してください。

ユーザー インターフェイスであるアドイン

アドインが UI である場合、次のことが必要です。

  1. ホスト アプリケーション、アドイン、およびパイプラインが、.NET Framework の「アドインおよび拡張機能」の説明に従って作成されている必要があります。

  2. アドインのコントラクト インターフェイスに INativeHandleContract を実装する必要があります。

  3. ホスト アプリケーションに渡されるアドインが、直接または間接的に、FrameworkElement から派生している必要があります。

  4. アドインは、分離境界を越える前に FrameworkElement から INativeHandleContract に変換される必要があります。

  5. アドインは、分離境界を越えた後に INativeHandleContract から FrameworkElement に変換される必要があります。

  6. ホスト アプリケーションは、返された FrameworkElement を表示します。

UI であるアドインを実装する方法の例については、「方法 : UI であるアドインを作成する」を参照してください。

複数の UI を返すアドイン

アドインが提供する複数の UIs をホスト アプリケーションが表示するケースはよくあります。 たとえば、UI であるアドインが、ホスト アプリケーションにステータス情報も UI として提供するとします。 このようなアドインは、ユーザー インターフェイスを返すアドインのモデルとユーザー インターフェイスであるアドインのモデルの両方の手法を組み合わせることで実装できます。

アドインと XAML ブラウザー アプリケーション

ここまでの例では、ホスト アプリケーションはスタンドアロン アプリケーションとしてインストールされています。 XAML browser applications (XBAPs) はアドインをホストすることもできますが、そのためには次に示すビルドと実装の要件を満たす必要があります。

  • パイプライン (フォルダーとアセンブリ) とアドイン アセンブリを、クライアント コンピューターの ClickOnce アプリケーション キャッシュの、XBAP と同じフォルダーにダウンロードするよう、XBAP アプリケーション マニフェストを構成する必要があります。

  • アドインを探索して読み込む XBAP コードで、XBAP の ClickOnce アプリケーション キャッシュを、パイプラインとアドインの場所として使用する必要があります。

  • XBAP は、アドインが起点サイトにある圧縮しないファイルを参照する場合、アドインを特別なセキュリティ コンテキストの下で読み込む必要があります。XBAPs によってホストされる場合、アドインが参照できるのは、ホスト アプリケーションの起点サイトにある圧縮しないファイルのみです。

これらのタスクについて、次のサブセクションで詳しく説明します。

ClickOnce 配置のためのパイプラインとアドインの構成

XBAPs は、ClickOnce 配置キャッシュの安全なフォルダーにダウンロードされ、そこから実行されます。 XBAP でアドインをホストするには、パイプラインとアドインのアセンブリも同じ安全なフォルダーにダウンロードする必要があります。 これを行うには、パイプラインとアドインのどちらのアセンブリもダウンロード対象に含まれるよう、アプリケーション マニフェストを構成する必要があります。 これは、Visual Studio で行うのが最も簡単ですが、Visual Studio でパイプラインをアセンブリとして検出するには、パイプラインとアドインのアセンブリが、ホスト XBAP プロジェクトのルート フォルダーに存在する必要があります。

したがって、まず、パイプライン アセンブリとアドイン アセンブリの各プロジェクトのビルド出力を設定し、パイプラインとアドインのアセンブリを XBAP プロジェクトのルートにビルドします。 次の表は、ホストの XBAP プロジェクトと同じソリューションとルートのフォルダーに格納される、パイプライン アセンブリ プロジェクトとアドイン アセンブリ プロジェクトのビルド出力パスを示します。

表 1: XBAP でホストされるパイプライン アセンブリのビルド出力パス

パイプライン アセンブリ プロジェクト

ビルド出力パス

コントラクト

.. \HostXBAP\Contracts\

アドイン ビュー

.. \HostXBAP\AddInViews\

アドイン側のアダプター

.. \HostXBAP\AddInSideAdapters\

ホスト側のアダプター

.. \HostXBAP\HostSideAdapters\

アドイン

.. \HostXBAP\AddIns\WPFAddIn1

次に、パイプライン アセンブリとアドイン アセンブリを XBAPs コンテンツ ファイルとして Visual Studio に指定します。手順は次のとおりです。

  1. ソリューション エクスプローラーで各パイプライン フォルダーを右クリックし、[プロジェクトに含める] をクリックして、パイプラインとアドインのアセンブリをプロジェクトに含めます。

  2. [プロパティ] ウィンドウで、パイプライン アセンブリとアドイン アセンブリそれぞれについて、[ビルド アクション][コンテンツ] に設定します。

最後に、パイプラインとアドインのどちらのアセンブリ ファイルもダウンロード対象に含まれるよう、アプリケーション マニフェストを構成します。 ファイルは、XBAP アプリケーションが占有する ClickOnce キャッシュ内のフォルダーのルートにあるフォルダー内に存在している必要があります。 この構成は、次の手順に従って、Visual Studio で行うことができます。

  1. XBAP プロジェクトを右クリックし、[プロパティ][発行] の順にクリックし、[アプリケーション ファイル] をクリックします。

  2. [アプリケーション ファイル] ダイアログ ボックスで、各パイプラインとアドインの DLL の [発行の状況][含める (自動)] に設定し、各パイプラインとアドインの DLL の [ダウンロード グループ][(必要)] に設定します。

アプリケーション ベースからのパイプラインとアドインの使用

パイプラインとアドインが ClickOnce 配置用に構成されると、ClickOnce キャッシュ フォルダーに XBAP としてダウンロードされます。 このパイプラインとアドインを XBAP から使用するには、XBAP コードがそれらをアプリケーション ベースから取得する必要があります。 .NET Framework アドイン モデルのさまざまな型やメンバーは、パイプラインおよびアドインを使用できるよう、このシナリオ用に特別なサポートを提供しています。 パスは ApplicationBase 列挙値で識別されます。 この値を適切なアドイン メンバーのオーバーロードと併用することで、次のようなパイプラインを使用できます。

ホストの起点サイトへのアクセス

アドインが起点サイトのファイルを参照できるように、アドインはホスト アプリケーションと等価なセキュリティ分離を使用して読み込む必要があります。 このセキュリティ レベルは AddInSecurityLevel.Host 列挙値により識別され、アドインがアクティブ化されたときに Activate メソッドに渡されます。

WPF アドイン アーキテクチャ

これまで見てきたように、最上位のレベルでは、WPF を使用することによって、.NET Framework アドインで、(FrameworkElement から直接または間接的に派生した) UIs を、INativeHandleContractViewToContractAdapter、および ContractToViewAdapter を使用して実装できます。 その結果、ホスト アプリケーションに FrameworkElement が返され、ホスト アプリケーションの UI で表示されます。

簡単な UI アドイン シナリオでは、開発者に必要な詳細はこれだけです。 より複雑なシナリオ、特にレイアウト、リソース、データ バインドなど、追加 WPF サービスの活用を想定したシナリオでは、その利点と制約を把握するために UI をサポートする .NET Framework アドイン モデルが、WPF で拡張されるしくみについて詳しい知識が必要です。

基本的に、WPF は UI をアドインからホスト アプリケーションに渡しません。その代わり、WPF は UI の Win32 ウィンドウ ハンドルを WPF 相互運用性を使用して渡します。 つまり、アドインの UI がホスト アプリケーションに渡されると、次の処理が行われます。

  • アドイン側で、WPF は、ホスト アプリケーションによって表示される UI のウィンドウ ハンドルを取得します。 このウィンドウ ハンドルは、HwndSource から派生し、INativeHandleContract を実装する内部 WPF クラスによってカプセル化されます。 このクラスのインスタンスは、ViewToContractAdapter によって返され、アドインのアプリケーション ドメインからホスト アプリケーションのアプリケーション ドメインにマーシャリングされます。

  • ホスト アプリケーション側では、WPF は HwndSource を、HwndHost から派生し、INativeHandleContract を使用する内部 WPF クラスとして、再パッケージ化します。 このクラスのインスタンスは、ContractToViewAdapter によってホスト アプリケーションに返されます。

HwndHost は、ウィンドウ ハンドルによって特定される UIs を WPF UIs で表示するために存在します。 詳細については、「WPF と Win32 の相互運用性」を参照してください。

まとめると、INativeHandleContractViewToContractAdapter、および ContractToViewAdapter は、WPF UI のウィンドウ ハンドルを、アドインからホスト アプリケーションに渡すために存在します。渡されると、HwndHost によってカプセル化され、ホスト アプリケーションの UI を表示します。

メモメモ

ホスト アプリケーションは HwndHost を取得するので、ホスト アプリケーションは ContractToViewAdapter から返されるオブジェクトを、アドインによって実装された型 (UserControl など) に変換できません。

その特質上、HwndHost には、ホスト アプリケーションの使用に影響する制約があります。 ただし、WPF は、HwndHost をアドイン シナリオ用の一部の機能で拡張します。 その利点と制約について以下に説明します。

WPF アドインの利点

WPF アドイン UIs は、HwndHost から派生する内部クラスを使用してホスト アプリケーションで表示されるため、そのような UIs は、レイアウト、レンダリング、データ バインド、スタイル、テンプレート、リソースなどの WPF UI サービスに関して、HwndHost の機能の制約を受けます。 ただし、WPF は、その内部 HwndHost サブクラスを、次のような追加機能で強化します。

  • ホスト アプリケーションの UI とアドインの UI との間を Tab キーで移動できます。 "アドインが UI である" プログラミング モデルでは、アドインが完全に信頼されているか部分的に信頼されているかに関係なく、アドイン側のアダプターが QueryContract をオーバーライドして、Tab キーによる移動処理を有効にする必要があります。

  • ホスト アプリケーション UIs で表示されるアドイン UIs のアクセシビリティ要件を順守します。

  • アプリケーション ドメインが複数あるシナリオで WPF アプリケーションが安全に実行されます。

  • アドインがセキュリティ分離を使用して実行されている場合 (部分的に信頼されているセキュリティ サンドボックス)、アドイン UI ウィンドウ ハンドルへの不正アクセスを回避します。 ViewToContractAdapter を呼び出すことでこのセキュリティが保証されます。

    • "アドインが UI を返す" プログラミング モデルで、アドイン UI のウィンドウ ハンドルを分離境界を越えて渡す唯一の方法は、ViewToContractAdapter を呼び出すことです。

    • "アドインが UI である" プログラミング モデルでは、アドイン側のアダプターで QueryContract をオーバーライドして ViewToContractAdapter を呼び出すこと (前の例に従って) が、アドイン側のアダプターの QueryContract 実装をホスト側のアダプターから呼び出すことに相当する処理として必要です。

  • アプリケーション ドメインの実行を何重にも保護します。 アプリケーション ドメインの制約に起因して、アドイン アプリケーション ドメインでスローされた未処理の例外は、分離境界が存在していても、アプリケーション全体のクラッシュにつながります。 ただし、WPF アドイン モデルおよび .NET Framework アドイン モデルは、この問題を回避し、アプリケーションの安定性を向上させる簡単な手段を提供します。 UI を表示する WPF アドインは、ホスト アプリケーションが WPF アプリケーションである場合に、アプリケーション ドメインが実行されているスレッドの Dispatcher を作成します。 WPF アドインの DispatcherUnhandledException イベントを処理することで、アプリケーション ドメインで発生した未処理の例外をすべて検出できます。 Dispatcher は、CurrentDispatcher プロパティから取得できます。

WPF アドインの制約

WPF は、HwndSourceHwndHost、およびウィンドウ ハンドルによる既定の動作に利点をもたらしますが、ホスト アプリケーションで表示されるアドイン UIs に対する制約もあります。

  • ホスト アプリケーションで表示されるアドイン UIs では、ホスト アプリケーションのクリッピング動作が考慮されません。

  • 相互運用性シナリオの空域の概念もアドインに適用されます (「技術領域の概要」を参照)。

  • リソースの継承、データ バインディング、コマンド実行など、ホスト アプリケーションの UI サービスは、アドイン UIs で自動的に使用可能化されないためです。 このサービスをアドインに提供するには、パイプラインを更新する必要があります。

  • アドイン UI に回転、拡大縮小、傾斜などの変換は適用できません (「変換の概要」を参照)。

  • System.Drawing 名前空間の描画操作によって描画されるアドイン UIs 内のコンテンツに、アルファ ブレンド効果を含めることができます。 ただし、それを含むアドイン UI とホスト アプリケーション UI のいずれも、完全に不透明である必要があります。言い換えると、どちらについても Opacity プロパティが 1 に設定されている必要があります。

  • アドイン UI を含むホスト アプリケーションのウィンドウの AllowsTransparency プロパティが true の場合、アドインは非表示になります。 このことは、アドイン UI が完全に不透明 (Opacity プロパティの値が 1) の場合にも該当します。

  • アドイン UI は、同じトップレベル ウィンドウ内の他の WPF 要素より前面に表示する必要があります。

  • アドインの UI には、VisualBrush を使用して描画できる部分はありません。 その代わり、アドインは生成された UI のスナップショットを取り、コントラクトで定義されているメソッドを使用してホスト アプリケーションに渡すことができるビットマップを作成できます。

  • メディア ファイルをアドイン UI 内の MediaElement で再生することはできません。

  • ホスト アプリケーションがアドイン UI 用に生成されたマウス イベントを発生させたり、受け取ったりすることはなく、ホスト アプリケーション UI の IsMouseOver プロパティの値は false に設定されます。

  • アドイン UI 内のコントロール間を、フォーカスが移動しても、GotFocus イベントおよび LostFocus イベントをホスト アプリケーションで受け取ったり、発生したりすることはありません。

  • アドイン UI を含むホスト アプリケーション部分は、印刷時には白く出力されます。

  • アドイン UI によって作成されたすべてのディスパッチャー (「Dispatcher」を参照) は、ホスト アプリケーションが実行を継続する場合、オーナー アドインがアンロードされる前に手動でシャットダウンする必要があります。 コントラクトは、アドインがアンロードされる前にホスト アプリケーションがアドインにシグナルを送信するためのメソッドを実装でき、それによりアドイン UI がそのディスパッチャーをシャットダウンできます。

  • アドイン UI が InkCanvas である場合、または InkCanvas を含んでいる場合、そのアドインをアンロードすることはできません。

パフォーマンスの最適化

既定では、複数のアプリケーション ドメインが使用されていると、各アプリケーションで必要とされているさまざまな .NET Framework アセンブリがすべてそのアプリケーションのドメインに読み込まれます。 その結果、新しいアプリケーション ドメインを作成してその中でアプリケーションを起動するために必要な時間がパフォーマンスに影響します。 ただし、.NET Framework には、アプリケーションに必要なアセンブリが既に読み込まれている場合に、それをアプリケーション ドメイン間で共有するよう指示することで起動時間を短縮する手段が用意されています。 これを行うには、LoaderOptimizationAttribute 属性を使用します。これを、エントリ ポイント メソッド (Main) に適用する必要があります。 この場合、アプリケーション定義を実装するコードのみを使用する必要があります (「アプリケーション管理の概要」を参照)。

参照

参照

LoaderOptimizationAttribute

概念

アドインおよび拡張機能

アプリケーション ドメイン

その他の技術情報

.NET Framework Remoting Overview

Making Objects Remotable

方法のトピック