2017-02-10 35 views
1

作爲一個免責聲明,我對C#完全陌生。這就是說,我在C#中尋找一個輕量級的pub/sub庫,我可以使用它,類似於我習慣的Javascript中的this。不過,我能找到的是.NET版本4或更高版本。我必須使用.NET 3.5。所以我決定寫我自己的,我稱之爲EventBus。目標是讓其他類自由訂閱/發佈事件總線中預先定義的事件。然而,我發現C#中的「事件」不是一等公民,因此我無法將它作爲參數傳遞給函數。所以我決定傳遞枚舉來指示當前哪個事件感興趣。我的EventBus按預期正常工作,但正如你在我的代碼中看到的那樣,當我添加一個新事件時,我遇到了在所有3個函數中繼續寫開關事件的問題。這是我的代碼。如何使用C#中的反射註冊事件#

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#的反思在這種情況下可以如何提供幫助。也許一旦枚舉(或字符串)被傳遞來表示一個事件,它就會被用來使用反射來查找事件並執行操作?

+2

有了更多的上下文(它是爲了什麼?)有人可能能夠建議一個消息系統或接口或... –

+0

或者查看調節器模式。 – Nkosi

回答

2

你不需要反思,你可以使用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發佈/訂閱接口。

+0

噢好吧,所以這只是依賴於你自己的事件 - 偵聽器映射而不是通過C#給出的+ =運算符向listeners註冊事件? – jiminssy

+0

@jiminssy:事件處理程序列表用於有大量事件的對象,只有少數事件被分配給事件處理程序。 WinForm的'Control'廣泛使用事件處理程序列表。 – Sefe

+0

看起來,這可能能夠處理event:listener之間的1:N關係。那是對的嗎?在這種情況下,這正是我正在尋找的!然後,我只需在eventMap初始化中添加更多事件。我的一個問題是你正在做一個簡單的新的Object()到Dictionary中。我可以在這裏使用繼承來構建層次結構來介紹事件之間的關係嗎(例如,我想訂閱所有與鼠標相關的事件) – jiminssy