我试图想出一种通用方法来拦截 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);
}
}
问题(如上所述)是代码无法编译,因为事件本身无法从生产者类外部访问。我理解这是因为事件处理是作为私有(private)类实现的,所以看不到任何明显的解决方法。
是否有任何方法可以拦截和链接事件,使我能够在生成器类中保留标准事件语法?
我意识到我可以放弃事件,而只使用我自己的等效生产者/消费者代码,但我会失去事件的正常好处(例如,更具可读性/可维护性、正确的语法突出显示/自动完成等)
编辑 - 我还尝试摆弄 MulticastDelegate 类,但是当我编译代码时,我无法订阅事件(实际上 OnEvent 始终为空)。
最佳答案
而不是接受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);
}
关于C# 通用事件处理 - 链接/代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24494116/