ILGenerator: método creado Carga
-
08-10-2019 - |
Pregunta
Estoy utilizando System.Reflection.Emit, y en algún momento quiero crear un delegado de un 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
Me podría descubrir que para crear delegados de funciones estáticas se usa algo como esto:
ldnull
ldftn void class Test.MainClass::bar()
newobj instance void class Test.DelegateType::'.ctor'(object, native int)
Pero ahora estoy atascado. Necesito una manera de ldftn la MethodBuilder y entonces necesito una manera de emitir la instrucción para la siguiente línea. Y no tengo ni idea de cómo llegar a un constructor que acepta un int nativo.
¿Alguna sugerencia?
Solución
A native int
es un IntPtr
en C #.
Se puede obtener el ConstructorInfo
para el tipo de delegado utilizando Type.GetConstructor
:
var constructorInfo =
delegateType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) });
A continuación, puede emitir las instrucciones IL así:
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Ldftn, someMethodInfo);
il.Emit(OpCodes.Newobj, constructorInfo);
Otros consejos
La clase ILGenerator tiene una sobrecarga Emit que toma un MethodInfo, por lo que puede hacer algo como ilGenerator.Emit(Opcodes.ldftn, mi)
, donde mi
es el método al que desea llamar. Puede ser cualquier método que pueda encontrar con la API de reflexión, o incluso otro método que ha creado con un MethodBuilder (que deriva de MethodInfo
).
Del mismo modo, para llamar a un constructor que le emita una instrucción newobj proporcionando una ConstructorInfo para la sobrecarga de destino.