2011-01-21 29 views
7

我有下面的類,它有一個公共事件調用LengthChanged如何引用在C#中的事件

class Dimension 
{ 
    public int Length 
    { 
     get 
     { 
      return this.length; 
     } 
     set 
     { 
      if (this.length != value) 
      { 
       this.length = value; 
       this.OnLengthChanged(); 
      } 
    } 

    protected virtual void OnLengthChanged() 
    { 
     var handler = this.LengthChanged; 
     if (handler != null) 
     { 
      handler (this, System.EventArgs.Empty); 
     } 
    } 

    public event System.EventHandler LengthChanged; 

    private int length; 
} 

我希望能夠爲這個事件的方法稱爲Observer /註銷處理程序,它對Dimension課程一無所知。我已經提出了兩個方案,其中沒有一個是真正的滿足:

  1. 定義的接口ILengthChangedLengthChanged事件,然後確保Dimension實現ILengthChanged。然後,我必須爲我定義的每個接口提供一個Observer方法的實現。這絕不夠通用。我真的希望能夠簡單地傳遞對System.EventHandler事件的引用。

  2. 使用System.Action<System.EventHandler>回調在Observer方法註冊和註銷事件處理程序,就像這樣:

    類Foo { 公共無效觀察員(System.Action寄存器, System.Action註銷) { register(this.MyEventHandler);

    // keep track of the unregister callback, so that we can unregister 
        // our event handler later on, if needed... 
    } 
    
    private void MyEventHandler(object sender, System.EventArgs e) 
    { 
        ... 
    } 
    

    }

其隨後將被調用這樣的:

Foo foo = ...; 
Dimension dim = ...; 

foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x); 

和在被執行時,確實將結束與內部事件處理程序MyEventHandler佈線LengthChanged事件。但這不是很優雅。我會喜歡能夠寫這個代替:

Foo foo = ...; 
Dimension dim = ...; 

foo.Observer (dim.LengthChanged); 

但我不知道如何實現這一目標。也許我錯過了這裏真正明顯的東西?我猜想一些dynamic魔法可以做到這一點,但不會強制執行編譯時類型檢查:我不希望Observer的用戶通過引用不符合System.EventHandler事件簽名的事件。

回答

10

不幸的是沒有辦法做到這一點。一般來說,事件不是.NET中的頭等公民,儘管F#試圖在那裏推廣它們。

可以通過訂閱/取消訂閱委託或使用指示事件名稱的字符串。 (後者通常更短,但在編譯時顯然不太安全。)

這些是Reactive Extensions需要採取的方法 - 如果有更乾淨的方法,我肯定他們會使用那個:(

+0

如果人們像埃裏克·梅傑沒能拿出更清潔的解決方案,我懷疑事實上,沒有其他辦法可以做到這一點。很傷心......謝謝你的快速回復,Jon。 – 2011-01-21 09:09:48

2

事件不應該被傳遞到另一個方法,但是,你可以將委託傳遞給另一個方法,也許你正在尋找的只是一個簡單的公共委託而不是事件。

如果您的事件改變這個

public System.EventHandler LengthChanged; 

你可以簡單地通過LengthChanged來觀察這樣

Foo foo = ...; 
Dimension dim = ...; 
foo.Observer (dim.LengthChanged); 
+0

謝謝你的建議。不,我不能通過代表而不是事件;該事件可能會實現`add`和`remove`設置器,而且必須被定義爲一個完整的C#`事件`。 – 2011-01-21 09:07:38