「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
.NET FrameworkでAOPを実現するための手法の1つである
「透過プロキシ(RealProxy?クラス)」の概要、使用方法、
そして、サンプル コードについて説明する。
ココでは、.NET FrameworkでAOPを実現するための
手法の1つである透過プロキシにフォーカスしてこれを説明する。
透過プロキシ †
透過プロキシの概要 †
透過プロキシとは、種々のリモート処理 基盤技術を使用して
境界を越えオブジェクトを転送するためのプロキシである。
- ココでは、AOPを実現するための手法の1つとして透過プロキシを活用する。
- また、RealProxy?クラスは透過プロキシを開発するための開発基盤である。
捕捉:
- 転送されるオブジェクトは、MarshalByRefObject? クラスを継承する必要がある。
- MSDN > .NET Frameworkクラス ライブラリ > MarshalByRefObject?クラス
http://msdn.microsoft.com/ja-jp/library/system.marshalbyrefobject.aspx
MarshalByRefObject? の「Marshal」は、一般的には「鉄道 操車場」(分岐器、ハンプなどを経て目的の仕分線に送る設備。ヤードとも呼ばれる)を意味するが、IT用語としては、COMなどで実装されていた「マーシャリング」を指し、アプリケーション ドメイン、プロセス、開発技術などの各境界を越えて、オブジェクトを転送する技術の総称である。開発技術の境界を越えるための技術としては、アンマネージDLLマーシャリングなどがあり、.NETオブジェクト引数をWin32 DLLで使用可能なデータ型の引数に変換(またはその逆を)する。なお、ココでは、MarshalByRefObject?(マーシャリング)技術の詳細については触れない。
- RealProxy?クラスはabstract基本クラスであり、透過プロキシを開発する際は、このRealProxy?クラスを継承する必要がある。
透過プロキシの基本的な動作 †
以下、透過プロキシの基本的な動作を説明する。
(1) †
- クライアントは、使用したいオブジェクト(以降、オブジェクトAと称す)の情報を透過プロキシに通知し、
- 透過プロキシは、リモート処理 基盤技術を使用してオブジェクトAを生成する。
- オブジェクトを生成する方法として、下記の方法が考えられる。
- コンストラクタから、オブジェクト・インスタンスを直接受け取る方法
- コンストラクタから、クラス情報を受け取り、
これを使用してオブジェクト・インスタンスを生成する方法
- コンストラクタから、リテラルを受け取り、定義情報から対応するクラス情報を取得、
これを使用してオブジェクト・インスタンスを生成する方法
- クライアントはオブジェクトAの参照の変わりに透過プロキシの参照を得る。
この透過プロキシの参照は、オブジェクトAの型に設定することができるため、
クライアントは、あたかもオブジェクトAを直接操作できるかのように錯覚する。
(2) †
- 透過プロキシの参照は、オブジェクトAの型に設定されているので、
この型を使用してオブジェクトAに対する呼び出しが可能である。
- このオブジェクトAのクラス型を使用したオブジェクトAへの呼び出しは(実際は)、
透過プロキシを使用して呼び出しているので、始めに透過プロキシの
Invoke メソッドにより呼び出しがフックされる。
- 透過プロキシでは、継承したRealProxy?のInvokeメソッドをオーバーライドする必要がある。
(3) †
- 透過プロキシは、Invokeメソッド内でリモート処理 基盤技術を使用し、呼び出しを実際のオブジェクトに転送する。
- 透過プロキシのポイントは、透過プロキシのInvokeメソッドには、
呼び出しメソッドのメソッド シグネチャの情報が引数として与えられている点である。
- メソッド シグネチャとは、一般的に、
「メソッド名」、「パラメタ数と順序、パラメタの型」、「戻り値の型」などを意味する。
- 透過プロキシのInvokeメソッドから使用したいオブジェクトに呼び出しを転送する場合、
最終的にレイトバインド 技術を使用することになる。
- .NETでは、System.Reflection名前空間のクラスライブラリを使用してレイトバインドを実現する。
- レイトバインドを使用する場合は、メソッド シグネチャを固定する方式が主流であるが、
- 言語によっても異なるが、C++、C#のような「強い静的型付け」という言語的特性を持つ言語に於いては、
実行に任意のオブジェクトに対して任意のメソッド呼び出しを試みるという処理が許可されていないため。
- C++では、これを仮想関数呼び出しやCOMで実現する。
- C#では、System.Reflection名前空間のクラスライブラリを使用して実現する。
- これに対し、VBではobject型に任意のメソッド呼び出しを記述できる
- 透過プロキシのInvokeメソッドには、
呼び出しメソッドのメソッド シグネチャの情報が引数として与えられるため、
これを使用して、どのようなメソッド呼び出しも転送することができる。
透過プロキシでAOPを実現 †
透過プロキシの働きについては、前項で説明した通りである。
- ここまでの説明で明らかであるが、透過プロキシを使用したAOPの実現方法とは、
透過プロキシのInvoke メソッドにアスペクトを実装するだけの簡単なものである。
- ここでは、透過プロキシの本来の
「リモート処理 基盤技術を使用して境界を越えオブジェクトを転送する」
役割は不要であるため、その部分の実装も不要である。
- また、様々な仕掛け(定義情報など)を用いることで、
以下の様な機能を追加することも可能である。
- 以下からウィービングされるアスペクトのパターンを可変にする。
- コンストラクタに指定されたリテラル
- メソッドに指定されたアノテーション(クラス / メソッド属性)
- アスペクトの実装位置を、透過プロキシ上から他のモジュール上へ移動し、呼び出す処理を選択する。
- コンストラクタに指定されたリテラル
- メソッドに指定されたアノテーション(クラス / メソッド属性)
しかし、ココでは、これらの応用的な利用方法までは説明しない。
動作確認用のサンプル プログラム †
- 透過プロキシを使用したAOPの動作確認用
サンプル プログラムを用いて、AOPの実装方法を説明する。
- サンプル プログラムはConsoleアプリケーションで作成されている。
- プロジェクトの構成は次のようになっている。
- クラス(モジュール)一覧
項番 | クラス(モジュール) | 説明 |
1 | TG.cs | ターゲット クラス(ココで言うオブジェクトA |
2 | PR1.cs | 透過プロキシ1(オブジェクトAのインスタンスを渡すバージョン |
3 | PR2.cs | 透過プロキシ2(オブジェクトAのクラス型情報を渡すバージョン |
4 | MyInt?.cs | 参照型を引数に使用した場合の動作検証に用いるクラス |
5 | Program.cs | 各種テスト ケースを実行するエントリポイント メソッド |
ターゲット クラス †
ターゲット クラスは、本書で説明した「オブジェクトA」、
すなわち、クライアントが使用したいオブジェクトのことである。
実装のポイントは、MarshalByRefObject?クラスを継承することであり、その他は任意の実装が可能である。
サンプル プログラムでは、様々なシグネチャのメソッドの呼び出しをテストするために、
様々なシグネチャのメソッドをターゲット クラスに実装してある。
透過プロキシ †
- 実装のポイントは、RealProxy?クラスを継承することである。
- サンプル プログラムには、アスペクトは実装していないので、
任意のアスペクトのパターンを、ここでウィービングするように実装する。
コンストラクタ †
また、透過プロキシ1、2で、コンストラクタの実装が若干異なる。
異なる点は、ターゲット クラスのオブジェクト インスタンスを生成する方法である。
- 透過プロキシ1
コンストラクタから、ターゲット クラスのオブジェクト インスタンスを直接受け取る。
- 透過プロキシ2
コンストラクタからクラス情報を受け取り、
これを使用してターゲット クラスのオブジェクト インスタンスを生成する。
Invokeメソッド †
透過プロキシ1、2ともInvokeメソッドの実装は同じである。
Tags: :プログラミング, :.NET開発