繁体   English   中英

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

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

作为免责声明,我是C#的新手。 这已经说了,我一直在寻找在C#中轻量级的pub / sub库我可以用这将是类似像这样在Javascript中,我习惯了。 但是,我所能找到的只是.NET 4或更高版本。 我必须使用.NET 3.5。 因此,我决定编写自己的文件,并将其称为EventBus。 目标是让其他类自由订阅/发布EventBus中预定义的事件。 但是我发现C#中的“事件”不是一等公民,因此我无法将其作为参数传递给函数。 因此,我决定通过枚举来表示当前关注的事件。 我的EventBus可以按预期工作,但是正如您在我的代码中看到的那样,每当添加新事件时,我都会遇到在所有3个函数中始终编写开关用例的问题。 这是我的代码。

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
}

有没有一种方法可以实现所有的订阅/取消订阅/发布操作,而无需使用类似switch的语句? 我想知道C#的反思如何在这种情况下有所帮助。 也许一旦枚举(或文字字符串)被传递以指示事件,它就可以通过反射来查找事件并执行操作?

您不需要反射,可以使用EventHandlerList 但是, EventHandlerList并不采用枚举,而是采用object作为键。 但是您可以使用中间字典轻松克服此限制:

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

您可能需要看一下IObservable<T> / IObserver<T>接口,它们是.NET发布/订阅接口。

暂无
暂无

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

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