2011-11-15 9 views
1

Reflection.Emit-Namespaceを使用して実行時に.NET-Typeを設計しています。.NETでReflection.Emitを使用してハードコーディングされた既存のメソッドを呼び出す

Dim AssemblyBuilder As AssemblyBuilder = Nothing 
Dim ModuleBuilder As ModuleBuilder = Nothing 
Dim TypeBuilder As TypeBuilder = Nothing 

Dim MethodBuilder As MethodBuilder 
Dim ReturnType As Type = Nothing 

AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(New AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.RunAndSave) 

ModuleBuilder = AssemblyBuilder.DefineDynamicModule("DynamicAsssembly", "DynamicAssembly.dll") 
TypeBuilder = ModuleBuilder.DefineType("DynamicType") 

MethodBuilder = TypeBuilder.DefineMethod("Do", MethodAttributes.Public, Nothing, Nothing) 

上記作品: 現在、私は、生成クラスに既存のメソッドを呼び出すメソッドを生成しようと思います。

MethodBuilder.GetILGenerator.EmitCall(OpCodes.Call, Me.GetType.GetMethod("DisplayString"), Nothing) 
MethodBuilder.GetILGenerator.Emit(OpCodes.Ret) 

ReturnType = TypeBuilder.CreateType() 
Activator.CreateInstance(ReturnType) 

これは、私は、一般的にやりたいたい:実行クラス自体に位置しているメソッドを呼び出します。しかし、以下を呼び出すと、例外がスローされます。

ReturnType.GetMethod("Do").Invoke(Activator.CreateInstance(ReturnType), Nothing) 

内部例外は(何かのような)です:InvalidProgramException、 "Common Language Runtimeが無効なプログラムを見つけました。"

私が電話を発する上記の行を、たとえば、

MethodBuilder.GetILGenerator.Emit(OpCodes.Ldstr, "test") 
MethodBuilder.GetILGenerator.EmitCall(OpCodes.Call, GetType(System.Windows.Forms.MessageBox).GetMethod("Show", {GetType(String)}), {GetType(String)}) 
MethodBuilder.GetILGenerator.Emit(OpCodes.Pop) 

正常に動作します。

実行中のアセンブリの種類とそのメンバにアクセスできないため、実際に問題が発生している可能性がありますが、それを実行するために何を変更する必要がありますか?

モモ

+0

'DisplayString'メソッドのシグニチャは何ですか? – svick

答えて

0

おかげで(MessageBox.Showがある)静的メソッドDisplayStringですか?

あなたは私のmangeled VB、そのかなり久しぶり与えるため

にメソッドをしてください呼び出すためにインスタンスを必要としていない場合は、このことができます

dim fieldBuilder as FieldBuilder = typeBuilder.DefineField(
       "o", Me.GetType(), 
       FieldAttributes.InitOnly | FieldAttributes.Private); 


dim constructor as ConstructorBuilder = typeBuilder.DefineConstructor(
       MethodAttributes.Public | 
       MethodAttributes.HideBySig | 
       MethodAttributes.SpecialName | 
       MethodAttributes.RTSpecialName, 
       CallingConventions.Standard, new[] { Me.GetType() }); 

//Make tho CTOR for the dynamic type, it needs to take an argument of the 
//instance to call the method on (in this case it will be Me) 

dim il as ILGenerator = constructor.GetILGenerator(); 

il.Emit(OpCodes.Ldarg_0); 

il.Emit(OpCodes.Call, baseCtor); 

il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Ldarg_1); 
il.Emit(OpCodes.Stfld, fieldBuilder); 

il.Emit(OpCodes.Ret); 

// Make the method 
il = methodBuilder.GetILGenerator(); 

il.Emit(OpCodes.Ldarg, 0); 
il.Emit(OpCodes.Ldfld, fieldBuilder); 
il.Emit(OpCodes.Ldstr, 'test'); 

il.Emit(OpCodes.Callvirt, Me.GetType.GetMethod ... 
il.Emit(OpCodes.Ret); 

)希望を。

何を出す必要があるのか​​を学ぶ最も良い方法の1つは、通常どおりにクラスを書いてからIL DASMを使用してからOpCodesをコピーすることです。

+0

多くの感謝!私はクラスからインスタンスを取得する必要があることを忘れてしまった。私はちょうどそれを静的(共有)メソッドにすることによってそれを試してみました。もう少し時間があれば、インスタンスメソッドを呼び出そうとします。 ILDASMのヒントをありがとう。私はすでにそれをしましたが、私はいつも何が起こっているのかを理解するのが難しいと感じています... – user1046555

関連する問題