简体   繁体   中英

How to register events using reflection in C#

As a disclaimer, I am completely new to C#. That been said, I was looking for a lightweight pub/sub library in C# I can use which would be similar to something like this in Javascript that I am used to. However all I could find was for .NET version 4 or higher. I have to use .NET 3.5. So I decided to write my own and I call this an EventBus. The goal is to have other classes to freely subscribe / publish events that are pre-defined in the EventBus. However I found out that the "event" in C# is not first class citizen so I couldn't pass that as a parameter to a function. So I decided to pass enum instead to indicate which event is of interest at the moment. My EventBus works fine as intended but as you can see in my code, I run into the problem of keep writing switch cases in all 3 functions whenever I add a new event. Here is my code.

public class EventBus {
    public delegate void EventListener(object source, EventArgs args);

    private static event EventListener MapLocationMarkerClicked;

    public static void Subscribe(Event eventToSub, EventListener listener)
    {
        switch(eventToSub)
        {
            case Event.MapLocationMarkerClicked:
                MapLocationMarkerClicked += listener;
                break;
        }
    }

    public static void Unsubscribe(Event eventToUnsub, EventListener listener)
    {
        switch (eventToUnsub)
        {
            case Event.MapLocationMarkerClicked:
                MapLocationMarkerClicked -= listener;
                break;
        }
    }

    public static void Publish(Event eventToPub, object source, EventArgs args)
    {
        switch (eventToPub)
        {
            case Event.MapLocationMarkerClicked:
                MapLocationMarkerClicked(source, args);
                break;
        }
    }
}

public enum Event
{
    MapLocationMarkerClicked
}

Is there a way to achieve all of the subscribe / unsubscribe / publish actions without switch statements like this? I was wondering how C#'s reflection could help in this situation. Maybe once the enum (or a literal string) is passed to indicate an event, it is used to find the event using reflection and perform the action?

You don't need reflection, you can use an EventHandlerList . However, the EventHandlerList does not take an enum, but an object as a key. But you can easily overcome this restriction with an intermediate dictionary:

static Dictionary<Event, object> eventMap = new Dictionary<Event, object>() { { Event.MapLocationMarkerClicked, new object() } };
static EventHandlerList events = new EventHandlerList();

public static void Subscribe(Event eventToSub, EventListener listener)
{
    events.AddHandler(eventMap[eventToSub], listener);
}

public static void Unsubscribe(Event eventToUnsub, EventListener listener)
{
    events.RemoveHandler(eventMap[eventToSub], listener);
}

public static void Publish(Event eventToPub, object source, EventArgs args)
{
    EventListener listener = (EventListener)events[eventMap[eventToSub]];
    listener?.Invoke(source, args);
}

You will probably want to take a look at the IObservable<T> / IObserver<T> interfaces, which are the .NET publish/subscribe interfaces.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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