2009-06-30 62 views
35

我正在使用一個在C#中轉發事件的類。我想知道是否有辦法做 它需要較少的代碼開銷。在C中轉發事件#

下面是我到目前爲止的一個例子。

class A 
{ 
    public event EventType EventA; 
} 

class B 
{ 
    A m_A = new A(); 
    public event EventType EventB; 

    public B() 
    { 
     m_A.EventA += OnEventA; 
    } 

    public void OnEventA() 
    { 
     if(EventB) 
     { 
     EventB(); 
     } 
    } 
} 

A級引發原始事件。 B類將其作爲EventB(它本質上是相同的事件)轉發。 A類對其他模塊是隱藏的,因此它們不能直接訂閱EventA。

我想要做的是減少類B中用於轉發事件的代碼開銷,因爲通常沒有真正處理類B中的事件。另外,我將有幾個不同的事件,因此它需要寫入B類中的很多OnEvent()方法只用於轉發事件。

是否有可能自動地以某種方式鏈接到EventA EventB,所以我有這樣的事情:

class B 
{ 
    A m_A = new A(); 
    public event EventType EventB; 

    public B() 
    { 
     m_A.EventA += EventB; // EventA automatically raises EventB. 
    } 
} 

我使用C#2.0編譯器BTW。

+0

大問題,特別是因爲你不應該忘記從EventA退訂,否則可能會發生內存泄漏(即使A不再需要,對象B仍會保留在內存中)。 – dbkk 2009-06-30 21:01:08

回答

64

絕對:

class B 
{ 
    private A m_a = new A(); 

    public event EventType EventB 
    { 
     add { m_a.EventA += value; } 
     remove { m_a.EventA -= value; } 
    } 
} 

換句話說,在EventB訂購/退訂代碼只是傳遞到EventA訂購/退訂請求。

但請注意,對於訂閱了EventB的訂閱者,這不允許您爲事件提高。這就像直接將某人的地址傳遞給大衆營銷公司,而您的原始方式更像是親自訂閱大衆營銷公司,並允許人們要求您將郵件副本發送給他們。

+11

這確實意味着`B.EventB`的訂戶得到了錯誤的發件人('A`而不是`B`),但是 - 這可能很重要... – 2009-06-30 20:22:21

9

IMO,你的原始代碼是(或多或少)是正確的。特別是,它允許您提供正確的sender(對於認爲他們正在訂閱B事件的用戶,應該是B實例)。

有一些技巧,以減少開銷在運行時,如果沒有簽約的情況下,但是這會增加更多代碼:

class B { 
    A m_A = new A(); 
    private EventType eventB; 
    public event EventType EventB { 
     add { // only subscribe when we have a subscriber ourselves 
      bool first = eventB == null; 
      eventB += value; 
      if(first && eventB != null) m_A.EventA += OnEventB; 
     } 
     remove { // unsubscribe if we have no more subscribers 
      eventB -= value; 
      if(eventB == null) m_A.EventA -= OnEventB; 
     } 
    } 

    protected void OnEventB(object sender, EventArgsType args) { 
     EventType handler = eventB; 
     if(handler !=null) { 
     handler(this, args); // note "this", not "sender" 
     } 
    } 
}