2011-11-15 103 views
1

我正在使用Reflection.Emit命名空間在運行時設計.NET類型。 目前,我即將產生這將調用一個已經存在的方法在所述生成的類的方法:在.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,「公共語言運行時找到了一個無效的程序。」

如果我用例如來自上面的線路來替換我發出呼叫,

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

DisplayString一個靜態方法(MessageBox.Show是)?

如果沒有,你將需要一個實例來調用方法上

請爲給我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); 

希望這會有所幫助。

學習需要發出什麼的最好方法之一就是像平常一樣使用寫類,然後使用IL DASM,然後就可以從中複製OpCodes。

+0

非常感謝!我沒有忘記我需要從我的課程中獲得一個實例。我只是試圖通過使它成爲一個靜態(共享)方法,它的工作。當我有更多時間時,我會嘗試調用實例方法。感謝與ILDASM的提示。我已經做到了,但我總是很難理解那裏發生的事情...... – user1046555

相關問題