简体   繁体   English

如何在C#中使用反射注册事件

[英]How to register events using reflection in C#

As a disclaimer, I am completely new to C#. 作为免责声明,我是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. 这已经说了,我一直在寻找在C#中轻量级的pub / sub库我可以用这将是类似像这样在Javascript中,我习惯了。 However all I could find was for .NET version 4 or higher. 但是,我所能找到的只是.NET 4或更高版本。 I have to use .NET 3.5. 我必须使用.NET 3.5。 So I decided to write my own and I call this an EventBus. 因此,我决定编写自己的文件,并将其称为EventBus。 The goal is to have other classes to freely subscribe / publish events that are pre-defined in the EventBus. 目标是让其他类自由订阅/发布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. 但是我发现C#中的“事件”不是一等公民,因此我无法将其作为参数传递给函数。 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. 我的EventBus可以按预期工作,但是正如您在我的代码中看到的那样,每当添加新事件时,我都会遇到在所有3个函数中始终编写开关用例的问题。 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? 有没有一种方法可以实现所有的订阅/取消订阅/发布操作,而无需使用类似switch的语句? I was wondering how C#'s reflection could help in this situation. 我想知道C#的反思如何在这种情况下有所帮助。 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 . 您不需要反射,可以使用EventHandlerList However, the EventHandlerList does not take an enum, but an object as a key. 但是, EventHandlerList并不采用枚举,而是采用object作为键。 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. 您可能需要看一下IObservable<T> / IObserver<T>接口,它们是.NET发布/订阅接口。

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

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