c#通用事件处理-链接/代理
本文关键字:链接 代理 事件处理 | 更新日期: 2023-09-27 18:10:46
我正试图想出一种通用的方法来拦截c#事件进行处理(例如日志记录,过滤,异步分发等),然后再将事件传递回其原始消费者。
举个例子,在正常的流程中你会有
class EventProducer
{
public event EventHandler<int> OnEvent;
internal void FireEvent()
{
if (OnEvent != null)
OnEvent(this, 1);
}
}
class EventConsumer
{
public EventConsumer(EventProducer producer)
{
producer.OnEvent += eventHandler;
}
public void eventHandler(object sender, int e)
{
Debug.WriteLine("Consumed " + e);
}
}
在我的例子中,我想在两者之间插入一个额外的步骤。就像
//event consumer
class EventConsumer
{
//use this to handle one particular event (EventProducer.OnEvent)
InterceptEventHandler<int> EventHandler;
public EventConsumer(EventProducer producer)
{
//just one line of code to insert an event handler to do what I need
//but whoops - cant refer to OnEvent outside of the producer
EventHandler = new InterceptEventHandler<int>(producer.OnEvent, eventHandler);
}
public void eventHandler(object sender, int e)
{
Debug.WriteLine("Consumed " + e);
}
}
//intercepts events, does something with them, then forwards them to original consumer
class InterceptEventHandler<T>
{
public EventHandler<T> Callback;
public InterceptEventHandler(EventHandler<T> eventHook, EventHandler<T> callback)
{
//save callback
Callback = callback;
//subscribe ourselves to the specified event
eventHook += interceptHandler;
}
public void interceptHandler(object sender, T e)
{
//do something with the event here
Debug.WriteLine("Intercepted " + e.ToString());
//then pass callback back to original consumer
Callback(sender, e);
}
}
问题(如上所述)是代码不能编译,因为事件本身不能从外部生产者类访问。我理解这是因为事件处理是作为私有类实现的,所以看不到任何明显的方法来解决这个问题。
是否有任何方法来拦截和链事件,这将允许我保持在生产者类的标准事件语法?
我意识到我可以放弃事件,只使用我自己等效的生产者/消费者代码,但我将失去事件的正常好处(例如更具可读性/可维护性,正确的语法高亮/自动完成等)
编辑-我也试着摆弄周围的MulticastDelegate类,但当我得到代码编译,我不能得到事件订阅(有效的OnEvent总是null)。
与其接受当然不是事件类型的EventHandler
,不如接受代表订阅该事件的操作的Action<EventHandler>
:
public class InterceptEventHandler
{
public static void Attach<T>(Action<EventHandler<T>> eventHook,
EventHandler<T> callback)
{
eventHook((sender, args) =>
{
doStuffOnFire(sender, args);
callback(sender, args);
});
}
private static void doStuffOnFire<T>(object sender, T e)
{
//...
}
}
你可以这样调用它:
public EventConsumer(EventProducer producer)
{
InterceptEventHandler.Attach<int>(
handler => producer.OnEvent += handler,
eventHandler);
}