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)。

c#通用事件处理-链接/代理

与其接受当然不是事件类型的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);
}