Grundsätzlich akzeptiere ich einen Ereignisnamen als Zeichenfolge, um die EventInfo
zu erhalten. Dann entdecke ich den Event-Handler-Typ und den Event-Argumenttyp mithilfe der Reflektion, indem ich einen neuen Delegaten dieses Typs() erstelle und ihn mit dem Event verknüpfe. Wann immer myEventHandler
aufgerufen wird, muss ich Downcast und übergeben Sie die Argumente an den Handler.IL Emit zum Aufrufen einer Delegat-Instanz?
Mein Code ist wie folgt. Der 'Handler' muss über myEventHandler
aufgerufen werden, wenn 'd' aufgerufen wird. Ich brauche etwas Reflektionscode dort, wo ich hingehe ???. Irgendwelche Gedanken?
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: Basierend auf Beobachtungen über Reflektor.
Die Reflektor-Code für ein manuell codiertes Szenario erzeugt wird
.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
}
Und das ist, was habe ich versucht, auf dieser Grundlage.
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);
Aber dies einen Laufzeitfehler verursacht:
'Calling convention must be varargs'
Wahrscheinlich bin ich etwas fehlt, brauchen einen besseren Blick in IL haben.
Der Trick hier ist immer einfach den Code in C# schreiben und reflector/ILDASM verwenden, um die IL zu betrachten. Ich würde schätzen, eine Kombination von Id, Castclass und Callvirt –
Yep zugestimmt. Ich werde diesen Weg nehmen, aber dachte, dass jede Reflexion Ninjas in SO ausstrahlt, kann das schnell darauf hinweisen – amazedsaint
Noch einmal schauen - wo befindet sich "Handler"? relativ zu den Argumenten? Ich denke, es wird ein Schmerz sein, die beiden zusammenzubringen. Es sieht so aus, als ob die C# -Version eine Capture-Klasse verwendet, aber Ihre dynamische Methode zur Zeit ist statisch, so dass Sie keinen Zustand verschieben können ... –