Fondamentalmente, sto accettando un nome evento come stringa, per ottenere il EventInfo
. Quindi, sto scoprendo il tipo di gestore eventi e il tipo di argomento evento utilizzando la reflection, creando un nuovo delegato di quel tipo (myEventHandler
) e collegandolo all'evento. Quando viene invocato lo , ho bisogno di downcast e passare gli argomenti al gestore.IL Emetti per il richiamo di un'istanza delegata?
Il mio codice è come di seguito. Il "gestore" deve essere invocato tramite myEventHandler
, quando viene invocato mai "d". Ho bisogno di avere qualche codice di emettere Reflection lì dove ho messo ???. qualche idea?
EventHandler handler = delegate(object sender, EventArgs eventArgs)
{
//something will happen here
};
Type[] typeArgs = { typeof(object), derivedEventArgsType };
DynamicMethod myEventHandler = new DynamicMethod("", typeof(void), typeArgs);
var ilgen = myEventHandler.GetILGenerator();
//What should be the IL code here to
//cast derviedEventArgs to EventArgs and
//invoke the 'handler' above??????
ilgen.Emit(OpCodes.Pop);
ilgen.Emit(OpCodes.Ret);
Delegate d = dynamic.CreateDelegate(derviedEventHandlerType);
//addMethod is the add MethodInfo for an Event
addMethod.Invoke(target, new object[] { d });
Edit: Sulla base di osservazioni via riflettore.
Il riflettore codice generato per uno scenario in codice manualmente è
.method public hidebysig instance void <Main>b__1(object sender, class ConsoleApplication2.MyEventArgs e) cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldarg.0
L_0002: ldfld class [mscorlib]System.EventHandler ConsoleApplication2.Program/<>c__DisplayClass3::handler
L_0007: ldarg.1
L_0008: ldarg.2
L_0009: callvirt instance void [mscorlib]System.EventHandler::Invoke(object, class [mscorlib]System.EventArgs)
L_000e: nop
L_000f: ret
}
E questo è quello che ho provato sulla base di questo.
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld,eh.GetType().GetField("handler"));
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Ldarg_2);
ilgen.EmitCall(OpCodes.Callvirt,eh.handler.Method,
new Type[]{ typeof(object), typeof(EventArgs) });
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ret);
Ma questo sta causando un errore di tempo di esecuzione:
'Calling convention must be varargs'
Probabilmente mi manca qualcosa, hanno bisogno di avere un aspetto migliore in IL.
Il trucco qui è sempre semplicemente scrivere il codice desiderato in C# e usare reflector/ILDASM per guardare l'IL. Vorrei indovinare una combinazione di ld, castclass e callvirt –
Sì concordato. Prenderò questa strada, ma ho pensato che qualsiasi Reflection emettere Ninjas in SO potrebbe rapidamente farlo notare – amazedsaint
Guardando ancora - dove risiede il "gestore"? rispetto agli arg? Sto pensando che sarà un dolore riunire i due. Sembra che la versione C# usi una classe di acquisizione, ma il tuo metodo dinamico al minuto è statico, quindi da nessuna parte spingere qualsiasi stato ... –