По сути, я принимаю имя события в виде строки, чтобы получить EventInfo
. Затем я обнаруживаю тип обработчика события и тип аргумента события, используя отражение, создавая новый делегат этого типа (myEventHandler
) и подключая его к событию. Когда когда-либо myEventHandler
вызывается, мне нужно уменьшить и передать аргументы обработчику.
Мой код, как показано ниже. «Обработчик» должен вызываться через myEventHandler
, когда всегда вызывается «d». Мне нужно иметь какой-нибудь код отражения Reflection там, где я положил ??? Есть мысли?
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 });
Редактировать: На основе наблюдений с помощью рефлектора.
Код, созданный рефлектором для сценария с ручным кодированием:
.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
}
И это то, что я пытался, основываясь на этом.
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);
Но это вызывает ошибку времени выполнения:
«Соглашение о вызовах должно быть varargs»
Возможно, я что-то упустил, мне нужно лучше изучить ИЛ.