Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# generic event handling - chaining/proxy

I'm trying to come up with a generic way to intercept C# events for processing (e.g. logging, filtering, distributing asynchronously etc.), before passing the event back on to its original consumer.

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 (e.g. 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).

like image 890
steve cook Avatar asked Oct 22 '25 02:10

steve cook


1 Answers

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:

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);
}
like image 127
Servy Avatar answered Oct 24 '25 15:10

Servy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!