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

时间:2014-06-30 15:50:27

标签: c# events generics event-handling

我试图想出一种通用的方法来拦截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);
    }
}

问题(如上所述)是代码无法编译,因为事件本身不能从生产者类外部访问。我理解这是因为事件处理是作为私人类实现的,因此无法看到任何明显的方法。

有没有办法拦截和链接允许我在生产者类中保留标准事件语法的事件?

我意识到我可以放弃事件,只使用我自己的等效生产者/消费者代码,但我将失去事件的正常好处(例如,更易读/可维护,正确的语法突出显示/自动完成等)< / p> 编辑 - 我也试图摆弄MulticastDelegate类,但是当我得到编译代码时,我无法获得要订阅的事件(实际上OnEvent总是为空)。

1 个答案:

答案 0 :(得分:5)

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