简体   繁体   English

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

[英]C# generic event handling - chaining/proxy

I'm trying to come up with a generic way to intercept C# events for processing (eg logging, filtering, distributing asynchronously etc.), before passing the event back on to its original consumer. 我试图提出一种通用方法来拦截C#事件以进行处理(例如,记录,过滤,异步分发等),然后再将事件传递回其原始使用者。

So to give an example, in the normal flow of things you'd have 举个例子,在正常情况下

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);
    }

}

In my case, I'd want to insert an additional step between the two.. something like 就我而言,我想在两者之间插入一个额外的步骤。

//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);
    }
}

The problem (as commented above) is that the code doesn't compile because the events themselves are not accessible from outside the producer class. 问题(如上所述)是代码无法编译,因为事件本身无法从生产者类外部访问。 I understand this is because the event handling is implemented as a private class, so can't see any obvious way around this. 我了解这是因为事件处理是作为私有类实现的,因此看不到任何明显的解决方法。

Is there any way to intercept and chain events that would allow me to keep the standard event syntax in producer classes? 有什么方法可以拦截和链接事件,从而使我可以将标准事件语法保留在生产者类中?

I realise that I can abandon events, and just use my own equivalent producer/consumer code, but i'll lose the normal benefits of events (eg more readable/maintainable, proper syntax highlighting/autocomplete etc.) 我意识到我可以放弃事件,而只使用自己的等效生产者/消费者代码,但是我将失去事件的常规好处(例如,更具可读性/可维护性,正确的语法突出显示/自动完成等)

EDIT - I also tried fiddling around with the MulticastDelegate class, but while I got the code to compile, I couldn't get the events to be subscribed (effectively OnEvent was always null). 编辑-我也尝试摆弄MulticastDelegate类,但是虽然我可以编译代码,但无法订阅事件(实际上OnEvent始终为null)。

Rather than accepting an EventHandler which is of course not the type of an event, accept an Action<EventHandler> which represents an action that subscribes to the event: 而不是接受当然不是事件类型的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)
    {
        //...
    }
}

You would then call it like so: 然后,您可以这样称呼它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM