使用.NET中的Reflection.Emit调用硬编码的现有方法

时间:2011-11-15 00:09:04

标签: .net vb.net reflection reflection.emit

我正在使用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)

它工作正常。

我认为发生了一个问题,因为执行的程序集类型及其成员是不可访问的,但是这是真的,我可以改变什么来让它运行?

由于

1 个答案:

答案 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。