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

ste*_*ook 2 c# generics events 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);
    }

}
Run Code Online (Sandbox Code Playgroud)

就我而言,我想在两者之间插入一个额外的步骤......就像

//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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

是否有任何方法可以拦截和链接允许我在生产者类中保留标准事件语法的事件?

我意识到我可以放弃事件,只使用我自己的等效生产者/消费者代码,但我将失去事件的正常好处(例如更易读/可维护,正确的语法突出显示/自动完成等)

编辑 - 我也试图摆弄MulticastDelegate类,但是当我得到编译的代码时,我无法获得要订阅的事件(实际上OnEvent总是为null).

Ser*_*rvy 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)
    {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你会这样称呼它:

public EventConsumer(EventProducer producer)
{
    InterceptEventHandler.Attach<int>(
        handler => producer.OnEvent += handler,
        eventHandler);
}
Run Code Online (Sandbox Code Playgroud)