我的代码归结为实际问题:(来自一个较大的单元测试项目)
// define all needed delegates for all events in myInstance
EventHandler oea = (o, ea) => GenericEventHandler(o, ea);
EventHandler<int> oi = (o, i) => GenericEventHandler(o, i);
// more
myInstance.GetType().GetEvents().Foreach(ei => {
// here I check the delegate of EventInfo to se which handler to use
....
AssignEvent(myItem, ei, oea); // or
AssignEvent(myItem, ei, oi); // or even more
....
});
...
private static void AssignEvent(object instance, EventInfo @event, Delegate handler)
{
var iName = instance.GetType().Name;
WriteTrace($"Assign {@event.EventHandlerType.Name} to {iName}.{@event.Name}");
@event.AddEventHandler(instance, handler);
}
private static void GenericEventHandler(params object[] o)
{
WriteTrace("$Event from {....} invoked");
}
```
我想知道在运行时调用处理程序的事件名称。 @event.Name 就在那里,但我如何让处理程序知道它。
由于事件处理程序以这种方式连接,因此 GenericEventHandler 中的 StackTrace 不包含任何有关事件名称的线索。
我已经研究了 DynamicMethod、Reflection、Expressions 等等,但找不到实现它的方法。
我想远离 Emit 和 IL。
我认为你可以通过一些关闭操作来做到这一点:
void Main() {
var item = new A();
var eventInfo = item.GetType().GetEvents().FirstOrDefault();
EventHandler<int> oi = (o, i) => GenericEventHandler(eventInfo, o, i);
AssignEvent(item, eventInfo, oi);
item.InvokeEvent();
}
private static void GenericEventHandler(EventInfo eventInfo, params object[] o) {
Console.WriteLine($"Event from {eventInfo.Name} invoked");
}
private static void AssignEvent(object instance, EventInfo @event, Delegate handler) {
var iName = instance.GetType().Name;
@event.AddEventHandler(instance, handler);
}
class A {
public event EventHandler<int> SomeEvent;
public void InvokeEvent() {
SomeEvent.Invoke(this, 42);
}
}