リモート処理可能オブジェクトとリモート処理不可能オブジェクト
あるアプリケーション ドメイン内で生成され、そのアプリケーション ドメインに固有のオブジェクトは、そのドメインからは直接呼び出すことができます。しかし、そのオブジェクトをドメインの外部から利用する場合は、特別の処理が必要になります。どの型のオブジェクトでもドメイン境界を越えて効率的に公開または利用できるわけではありません。したがって、公開するオブジェクトの型は、アプリケーションでの用途に応じて判断する必要があります。分散アプリケーションで使用する場合、オブジェクトは次の 2 つのシンプルなカテゴリに分類できます。リモート処理不可能オブジェクトとリモート処理可能オブジェクトです。
リモート処理不可能オブジェクト
一部のオブジェクトは、アプリケーション ドメインから離れることができません。シリアル化のメソッドを宣言しないため、マーシャリングされないからです。これらのリモート処理不可能オブジェクトは、それらが生成されたアプリケーション ドメイン内で使用するようにデザインされており、そのアプリケーション ドメインからは直接アクセスできます。.NET Framework クラス ライブラリのほとんどの基本クラスは、リモート処理不可能オブジェクトです。リモート処理不可能オブジェクトは、他のアプリケーション ドメイン内ではコピーまたはインスタンスの生成ができません。これらのオブジェクトは元のアプリケーション ドメインからしかアクセスできません。
リモート処理可能オブジェクト
リモート処理可能オブジェクトは、そのアプリケーション ドメインやコンテキストの外部から、プロキシを使用してアクセスまたはコピーできます。また、コピーはアプリケーション ドメインやコンテキストの外部に渡すことができます。つまり、リモート処理可能オブジェクトには、参照渡しができるものと、値渡しができるものがあります。
リモート処理可能オブジェクトは、広範囲な分散環境でも完全に動作できるオブジェクトです。リモート処理可能オブジェクトには、主として次の 2 種類があります。
値渡しでマーシャリングされるオブジェクト。これはアプリケーション ドメインからコピーされて渡されます。
参照渡しでマーシャリングされるオブジェクト。これに対してはプロキシが生成され、クライアントによってオブジェクトへのリモート アクセスに使用されます。
値渡しでマーシャリングされるオブジェクト
値渡しでマーシャリングされる (MBV : Marshal-By-Value) オブジェクトは、独自のシリアル化を実装する ISerializable の実装、または、システムにオブジェクトの自動的シリアル化を指示する SerializableAttribute による修飾、のいずれかの方法でシリアル化規則を宣言しますが、MarshalByRefObject を拡張することはありません。リモート処理システムは、これらのオブジェクトの完全なコピーを生成し、そのコピーを呼び出し元のアプリケーション ドメインに渡します。コピーが呼び出し元のアプリケーション ドメインに渡された後は、そのコピーに対する呼び出しはそのコピーに直接実行されます。また、引数として渡された MBV オブジェクトも値渡しになります。アプリケーションまたはコンテキストの境界を越えてクラスのインスタンスを値渡しするときは、SerializableAttribute 属性の宣言、または ISerializable の実装以外、特に何も行う必要はありません。
メモ : |
---|
.NET Framework のバージョン 1.1 以降では、リモート処理インフラストラクチャはサーバー上での特定の型の逆シリアル化を自動的には実行しません。これに該当するシナリオでは、サーバーの逆シリアル化のレベルを Full に設定して、サーバーが逆シリアル化を行い、MBV オブジェクトを使用できるようにする必要があります。詳細については、「.NET リモート処理での自動逆シリアル化」を参照してください。 |
MBV オブジェクトは、パフォーマンスや処理上の理由から、オブジェクトや実行できる機能の完全な状態をターゲットのアプリケーション ドメインに移動することが必要な場合に使用します。多くのシナリオでは、これによって、ネットワーク境界、プロセス境界、アプリケーション ドメイン境界を越えて行われる、時間とリソースを費やすラウンドトリップを減らすことができます。MBV オブジェクトは、オブジェクトの生成元であるアプリケーション ドメインから直接使用することもできます。この場合は、マーシャリングが行われないため、コピーも生成されず、アクセス効率が向上します。
その一方で、公開するオブジェクトが巨大な場合、完全なコピーを混雑したネットワーク内でやり取りすることは、アプリケーションにとって必ずしも良い選択とは言えません。そのうえ、コピーされたオブジェクトの状態を変更しても、元のアプリケーション ドメインにある元のオブジェクトには反映されません。抽象的なレベルでは、このシナリオは静的 HTML ページがクライアント ブラウザから要求された場合のシナリオに似ています。サーバーはファイルをコピーしてストリームに書き込み、送出して、その後は一切関与しません。それ以降の要求は、単に別のコピーに対する別の要求として処理されます。
既に ISerializable を実装しているクラスを拡張しない場合は、SerializableAttribute を使用して値渡しでマーシャリングされる型を作成します。この場合、型に対して ISerializable を実装する必要があります。
リモート処理システムでは、シリアル化可能なオブジェクトが広範に利用されます。リモート処理システムで ObjRef クラスによって表される、別のアプリケーション ドメインでのオブジェクトへの参照は、参照自体がシリアル化可能です。したがって、リモート処理システムはこの参照を正しくコピーして、要求に送信できます。IMessage を実装したメッセージ オブジェクトの場合も同様です。なぜならば、これらのメッセージ オブジェクトは、呼び出しデータやその他の必要なオブジェクト参照の汎用のコンテナであるからです。また、単純にデータを転送するオブジェクトも、多くの場合シリアル化できるオブジェクトです。たとえば、DataSet は、ISerializable を実装した MarshalByValueComponent を拡張します。
ユーザー定義例外のリモート処理
システム定義の例外は、すべて値渡しでマーシャリングされる型であり、ISerializable インターフェイスを実装しています。リモート オブジェクトがこの例外をスローするとき、リモート構成で許可されていれば、例外は自動的に呼び出し元にコピーされます。.NET Framework のバージョン 1.1 以降では、例外を呼び出し元に送る機能を有効にするには、<customErrors> 要素を off に設定する必要があります。
リモート オブジェクトによってスローされ、リモート呼び出し元によってキャッチできる例外の種類を作成する方法の詳細については、「方法 : リモート オブジェクトからスローできる例外の種類を作成する」を参照してください。
参照渡しでマーシャリングされるオブジェクト
参照渡しでマーシャリングされる (MBR : Marshal-By-Reference) オブジェクトはリモート処理可能オブジェクトであり、System.MarshalByRefObject の拡張はできます。宣言したアクティベーションの種類に応じて、クライアントがそのアプリケーション ドメインで MBR オブジェクトのインスタンスを生成すると、.NET リモート処理インフラストラクチャが、呼び出し元のアプリケーション ドメイン内に MBR オブジェクトの代理のプロキシ オブジェクトを生成し、そのプロキシに対する参照を呼び出し元に返します。次に、クライアントはプロキシへの呼び出しを実行します。リモート処理はこれらの呼び出しをマーシャリングし、元のアプリケーション ドメインに返送し、実際のオブジェクトに対する呼び出しを行います。
メモ : |
---|
クライアントが MBR オブジェクトと同じアプリケーション ドメインにある場合、インフラストラクチャは MBR オブジェクトに対する直接の参照をクライアントに返し、マーシャリングのオーバーヘッドの発生を防ぎます。 |
MarshalByRefObject は、パラメータとして渡された場合は、呼び出しを受信すると別のアプリケーション ドメインでプロキシになります。MBR の戻り値と out パラメータは、同じ方法で機能します。
メモ : |
---|
.NET Framework のバージョン 1.1 以降では、リモート処理インフラストラクチャはサーバー上での特定の型の逆シリアル化を自動的には実行しません。たとえば、パラメータとして渡される MBR オブジェクトがサポートされるようにするには、サーバーの逆シリアル化のレベルを Full に設定して、サーバーが逆シリアル化を行い、MBR パラメータを使用できるようにする必要があります。詳細については、「.NET リモート処理での自動逆シリアル化」を参照してください。 |
MBR オブジェクトを使用するのは、オブジェクトや実行できる機能の状態を生成されたアプリケーション ドメイン内にとどめておく必要があるときです。たとえば、オペレーティング システム ハンドルとして使用する内部フィールドを持つオブジェクトは、MarshalByRefObject を拡張する必要があります。これは、オペレーティング システム ハンドルは、他のプロセスやコンピュータ内の他のアプリケーション ドメインでは意味がないためです。また、オブジェクトが極端に大きい場合、堅牢なサーバー上では正常に機能しても、33.6 Kbps モデムに有線送信された場合は機能しない可能性があります。
コンテキスト バインド オブジェクト
コンテキスト バインド オブジェクトは、System.ContextBoundObject から継承された MBR オブジェクトです。System.ContextBoundObject 自体は、System.MarshalByRefObject から継承されています。コンテキストは、その内部にあるオブジェクトに対して実行時に高度な環境を提供する、アプリケーション ドメインの下位概念と考えることができます。たとえば、コンテキストは、オブジェクトが同時に複数のスレッドからアクセスされないことを保証できます。すべてのアプリケーション ドメインが、既定のコンテキストを持っています。ほとんどのマネージ コードは、同じアプリケーション ドメイン内でそのドメインの既定のコンテキストを使用してオブジェクトを生成したりメンバを直接呼び出したりするため、コンテキストに関連する問題が発生することはありません。ContextBoundObject から継承されたすべての型は、同じドメイン内または他のドメイン内にある他のコンテキストに対して、プロキシとして公開されます。
たとえば、ある型にメソッドがあり、このメソッドはトランザクションの一部であるため、それが生成されたコンテキスト固有の規則による制限を受けているとします。オブジェクトがそれ自体のコンテキストからアクセスされ、システムがそのオブジェクトとメソッドに関連付けられているトランザクションに対して規則を適用できるようにするには、この型を ContextBoundObject から継承する必要があります。ContextBoundObject が同じアプリケーション ドメインにある別のコンテキストから呼び出されると、呼び出し元に対してプロキシが生成されますが、コンテキスト間の通信はチャネル システムを通じて行われるのではないため、この状況での呼び出しの効率性が向上します。
各境界を越えるには処理時間が必要なため、サーバーをリモート処理可能オブジェクトのどの型にするのかを決める前に、オブジェクトが越える境界を決める必要があります。特定のコンテキストに固有のオブジェクトのみが、そのコンテキストから直接アクセスできます。特定のアプリケーション ドメインに固有のオブジェクトにも同じことが当てはまります。いずれかのオブジェクトにリモートにアクセスするには、オブジェクト固有の境界の内部からサーバー オブジェクトを呼び出す前に、リモート処理システムがコンテキスト境界またはアプリケーション境界、あるいはその両方を正常に越える必要があります。オブジェクトを呼び出すときにコンテキストをチェックしなくてよい場合は、リモート型で ContextBoundObject を拡張しないようにする必要があります。この場合には、MarshalByRefObject の方がパフォーマンスが優れています。コンテキストのチェックが必要な場合は ContextBoundObject を拡張する必要がありますが、追加の境界はオブジェクトに対する呼び出しが行われる前に越える必要があります。
公開のスコープ
それぞれのリモート処理システムには、リモートで使用できるメンバとメンバの型の種類を決定する固有の方法があります。.NET リモート処理は他のアプリケーション ドメインに対してオブジェクトをローカルであるかのように公開しますが、次に示す例外もあります。
静的メンバ
静的フィールドと静的メソッドはリモートにアクセスされることはないため、フィールドへのアクセスはダイレクト メモリを通じて行われます。つまり、.NET リモート処理では、常に一定の形式のインスタンス メンバを処理します。
インスタンス フィールドとアクセサ
インスタンス フィールドおよびアクセサ メソッドの場合は、実行時にシステムによってオブジェクトがプロキシかどうかをチェックされます。オブジェクトがプロキシでない場合は、フィールドには直接アクセスされます。それ以外の場合、プロキシは呼び出し元にアクセサを提供します。
プライベート メソッド
プライベート メソッドはリモートにアクセスできません。デリゲートをリモートでラップしてプライベート メソッドに渡すことはできません。
デリゲート
デリゲートは値渡しでマーシャリングされるオブジェクトです。デリゲート内のオブジェクトには、リモート処理可能オブジェクト、つまりシリアル化可能な MarshalByRefObject オブジェクト、または ContextBoundObject オブジェクトのうちの任意の種類を使用できます。ただ 1 つの例外として、インターフェイス メソッドへのデリゲートはリモート処理できません。デリゲートは、インターフェイス メソッドの実装をラップし、サーバーで利用できるようにするために、クライアントの型情報を要求します。
Object メソッド上のメソッドのオーバーライド
パフォーマンス上の理由から、Object メソッド上の仮想メソッドは、呼び出されたアプリケーション ドメインで常にローカルに実行されます。次に示すメソッドがリモート オブジェクトでオーバーライドされている場合、これらのメソッドに対する呼び出しは、リモート オブジェクトに対してだけ行われます。
Equals
この仮想メソッドがオーバーライドされている場合は、リモートでだけ実行されます。
GetHashCode
このメソッドはローカルに実行されます。
ToString
この仮想メソッドがオーバーライドされている場合は、リモートでだけ実行されます。
Equals (静的バージョン)
このメソッドはローカルに実行されます。
MemberwiseClone
このメソッドはローカルに実行されます。
参照
処理手順
方法 : リモート オブジェクトからスローできる例外の種類を作成する