アセンブリのレイト・バインディングとリフレクションによるメソッド呼び出し
アセンブリのレイトバインディングとリフレクションによるメソッド呼び出し
始めにお断りしておきますと、レイトバインディングもリフレクションももともと .NET Framework が備えているもので、 知っている人には何ら新しいトピックではありません。何かあるんじゃないかな、と期待された方ごめんなさい m(_ _)m
最近、プラグイン的な仕組みを実装することがあり、レイトバインディングな箇所を実装したので、せっかくなので資料をまとめてみました。
この資料で使うサンプルアセンブリ
この資料では次のコードで、アセンブリ(ライブラリ、DLL)を作ります。この名前を MyDll1.dll とします。
using System.Windows.Forms; namespace MyDll1 { public class MyClass1 { public static int MyStaticMethod( int i , int j ) { return i+j; } public void MySayHello( string name ) { MessageBox.Show( string.Format( "Hello, {0}-san!" , name ) ); } } }
まず、名前空間は MyDll1 で、クラス名は MyClass1 です。
一つ目のメソッドはスタティックメソッドで、MyStaticMethod という名前です (どうです?サンプルプログラムらしいでしょ?) int の引数を二つ受け取り、戻り値としてそれらの足し算結果を返しています。(これもいかにもサンプルです)
二つ目のメソッドはインスタンスメソッドの MySayHello です。 これは string の引数を受け取って、それに Hello ... san! という文字をくっつけてメッセージボックスを表示します。
こんなコードで、MyDll1.dll を作ります。
これを他のプログラムから実行時にロードして、その中のメソッド (つまり、MyStaticMethod と MySayHello) を呼び出しましょう。
ちなみに、導入部でちらっと触れましたが、このような仕組みは実行時までどのアセンブリのメソッドを呼ぶかわからないような場合に使うと便利です。
例えば、自分のプログラムに対して、サードパーティのプラグインを受け付ける場合などです。設定ファイルにプラグインのパスを書いておき、 実行時に DLL を探して、その中のメソッドを呼び出すようなことが、この仕組みを使うと出来るわけです。
呼び出し例
スタティックメソッドの呼び出し
まずはスタティックメソッドの呼び出し例です。
Assembly a = Assembly.LoadFile( @"C:\temp\MyDll1.dll" ); Type t = a.GetType( "MyDll1.MyClass1" ); MethodInfo mi = t.GetMethod( "MyStaticMethod" , BindingFlags.Public | BindingFlags.Static ); object[] parameters = new object[] { 1 , 2 }; object ret = mi.Invoke( null , parameters ); MessageBox.Show( ret.ToString() );
アセンブリのパスを指定して Assembly.LoadFile でロードします。クラス名を指定して、型 (Type) を取得します。 Type を利用して MethodInfo を取得して、メソッドインフォの Invoke メソッドでメソッドを呼び出します。
Type を取得した後、インスタンスを生成することなく、メソッドを呼び出せているところがポイントです。
インスタンスメソッドの呼び出し
次にインスタンスメソッドの呼び出し例です。
Assembly a = Assembly.LoadFile( @"C:\temp\MyDll1.dll" ); Type t = a.GetType( "MyDll1.MyClass1" ); ConstructorInfo ci = t.GetConstructor( Type.EmptyTypes ); MethodInfo mi = t.GetMethod( "MySayHello" , BindingFlags.Public | BindingFlags.Instance ); object obj = ci.Invoke( null ); object[] parameters = new object[] { "Keisuke" }; mi.Invoke( obj , parameters );
アセンブリのパスを指定して Assembly.LoadFile でロードします。クラス名を指定して、型 (Type) を取得します。 Type を利用して MethodInfo を取得します。
ここまではスタティックメソッドの場合と同一です。
しかしながら、インスタンスメソッドはインスタンスが必要です。(当然ながら)
そこで、インスタンスを生成するためにコンストラクタの情報を取得します。コンストラクタ情報 (ConstructorInfo) は、Type.GetConstructor メソッドで取得でき、 それの Invoke メソッドを呼ぶことによって、インスタンスが取得できます。
MethodInfo.Invoke の第一引数に、上で生成したインスタンスを渡すことによって、指定したインスタンスメソッドを呼び出すことが可能となります。