Вызов жестко закодированного существующего метода с Reflection.Emit в .NET - PullRequest
1 голос
/ 15 ноября 2011

Я разрабатываю .NET-тип во время выполнения, используя пространство имен Reflection.Emit-Name.В настоящее время я собираюсь сгенерировать метод, который вызывает уже существующий метод в генерирующем классе:

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 голосов
/ 15 ноября 2011

Является ли 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 для него, затем вы можете скопировать коды операций из этого.

...