Fondamentalement, j'accepte un nom d'événement sous forme de chaîne, pour obtenir le EventInfo
. Ensuite, je découvre le type de gestionnaire d'événement et le type d'argument d'événement en utilisant la réflexion, en créant un nouveau délégué de ce type (myEventHandler
), et en le reliant à l'événement. Quand jamais myEventHandler
est invoqué, j'ai besoin de downcast et passer les arguments au gestionnaire.IL Emettre pour appeler une instance de délégué?
Mon code est le suivant. Le 'gestionnaire' doit être appelé via myEventHandler
, quand jamais 'd' est invoqué. Je dois avoir un code d'émission de réflexion là où je mets ??? Des pensées?
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: Sur la base des observations via réflecteur.
Le réflecteur code généré pour un scénario codé manuellement est
.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
}
Et ce que j'ai essayé sur cette base.
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);
Mais cela provoque une erreur de temps d'exécution:
'Calling convention must be varargs'
Probablement je manque quelque chose, besoin d'avoir un meilleur regard sur IL.
L'astuce ici est toujours simplement d'écrire le code que vous voulez en C# et d'utiliser réflecteur/ILDASM pour regarder l'IL. Je devinerais une combinaison de ld, castclass, et callvirt –
Yep convenu. Je vais prendre cette route, mais je pense que toute Réflexion émise Ninjas dans SO peut rapidement le signaler – amazedsaint
En regardant à nouveau - où réside "gestionnaire"? par rapport aux args? Je pense que ça va être difficile de réunir les deux. Il semble que la version C# utilise une classe de capture, mais votre méthode dynamique à la minute est statique, donc nulle part pour pousser n'importe quel état ... –