2010-12-06 1 views
3

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

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.

Любые предложения?

+0

Интересный вопрос. Если вы не получите решение, вы можете отправить вызов на [Delegate.CreateDelegate] (http://msdn.microsoft.com/en-us/library/system.delegate.createdelegate.aspx). – dtb 2010-12-06 00:19:14

ответ

6

A native int - IntPtr в 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); 
0

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

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