我正在使用Reflection.Emit-Namespace在运行时设计.NET-Type。 目前,我即将生成一个方法,该方法在生成类中调用已存在的方法:
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 :(得分:0)
DisplayString
是静态方法(MessageBox.Show
是)吗?
如果不是,您将需要一个实例来调用
上的方法请给我管理好的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。