ILGenerator: загрузить созданный метод

Я использую System.Reflection.Emit и в какой-то момент хочу создать делегата из MethodBuilder:

MethodBuilder fooBuilder = createFooMethodBuilder();
ILGenerator ilGenerator = ...
Type delegateType = typeof(DelegateType);
LocalBuilder delegateVar = ilGenerator.DeclareLocal(delegateType);
//Somehow create emit instructions to create delegate from fooBuilder
//Store delegate in delegateVar using 

Я мог узнать, что для создания делегатов из статических функций используется что-то вроде этого:

ldnull 
ldftn void class Test.MainClass::bar()
newobj instance void class Test.DelegateType::'.ctor'(object, native int)

Но теперь я застрял. Мне нужен способ ldftn для MethodBuilder, а затем мне нужен способ выдать инструкцию для следующей строки. И я понятия не имею, как получить конструктор, который принимает собственный тип int.

Какие-либо предложения?


person luiscubal    schedule 06.12.2010    source источник
comment
Интересный вопрос. Если вы не получили решения, вы можете отправить вызов Delegate.CreateDelegate вместо этого.   -  person dtb    schedule 06.12.2010


Ответы (2)


A native int is an IntPtr in C#.

Вы можете получить ConstructorInfo для типа делегата, используя Type.GetConstructor:

var constructorInfo =
    delegateType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) });

Затем вы можете выдать инструкции IL следующим образом:

il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Ldftn, someMethodInfo);
il.Emit(OpCodes.Newobj, constructorInfo);
person dtb    schedule 06.12.2010

Класс ILGenerator имеет перегрузку Emit, которая принимает информацию о методе, поэтому вы можете сделать что-то вроде ilGenerator.Emit(Opcodes.ldftn, mi), где mi — это метод, который вы хотите вызвать. Это может быть любой метод, который вы нашли с помощью API отражения, или даже другой метод, созданный вами с помощью MethodBuilder (он происходит от MethodInfo).

Точно так же, чтобы вызвать конструктор, вы должны сгенерировать инструкцию newobj, предоставляющую ConstructorInfo для целевой перегрузки.

person Scott Wisniewski    schedule 06.12.2010