用反射调用硬编码的现有方法.在.net中发出



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

它工作得很好。

我假设发生了一个问题,因为执行程序集类型和它们的成员是不可访问的,但这是真的吗?我可以做些什么来让它运行?

感谢莫莫

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);

希望对你有帮助。

了解需要发出什么的最好方法之一是像往常一样使用write类,然后在其上使用IL DASM,然后您可以从中复制OpCodes。

相关内容

  • 没有找到相关文章

最新更新