2011-08-16 29 views
2

我把「事件」放在引號中,因爲我意識到這是一種語法糖,而不是真正的類型。有沒有辦法完成等同於通過引用傳遞「事件」?

我有一些事件被簡單地鏈接到另一個類中的匹配事件。因此,當事件引發,該通道就像是

雷塞 - >代理 - >用戶

所以在Proxy類我有這樣一個共同的模式:

Raiser.SomeEvent += 
    (_, args) => 
    { 
     if (this.SomeEvent != null) 
      this.SomeEvent(this, args); 
    }; 

收拾我代碼我想提出這個出去,返回一個新的委託包裝了上述事件調用代碼的另一種方法:

public static EventHandler GetHandlerDelegate(EventHandler handler, Object sender) 
{ 
    return 
     (_, args) => 
     {     
      if (handler != null) 
       handler(sender, args); 
     }; 
    }  

然後在代理我可以這樣做:

Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this); 

哪個更合適。

那麼這是好的,只要訂閱者不決定訂閱Proxy.SomeEvent 之後上面的調用。不幸的是,我沒有像我希望的那樣通過引用來傳遞「事件」。我現在明白了,我只是傳遞了調用列表,所以當OtherClass.SomeEvent發生並且調用匿名方法並調用它的「事件」(委託)時,只有當時已添加到該事件的代理我打電話給GetHandlerDelegate()。雖然這實際上足以滿足我目前的情況,但以這種方式進行編碼是不可接受的。

我讀過一些其他的SO問題,我收集了一些名爲Reactive Extensions的內容可能會有所幫助,但此時我正在尋找一個更簡單的解決方案(如果有的話)。 (如果沒有,我只是不會這樣做。)

有沒有另一種方法可以完成我想要做的事情,沒有缺點?


如果這個問題不清楚,請參閱my answer,希望有助於澄清它。

回答

0

因爲我原來做的目標:

Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this); 

是不可能的,我已經妥協,並拿出這樣的:

Raiser.SomeEvent += (_, args) => RaiseEvent(this.SomeEvent, this, args); 

GetHandlerDelegate()將返回其引發事件的委託,RaiseEvent()只是(你猜對了)引發了這個事件。

public static void RaiseEvent(EventHandler _event, Object sender, EventArgs args) 
{ 
    if (_event != null) 
     _event(sender, args); 
} 

並支持活動使用自定義的EventArgs:

public static void RaiseEvent<TArgs>(EventHandler<TArgs> _event, Object sender, TArgs args) 
    where TArgs : EventArgs 
{ 
    if (_event != null) 
     _event(sender, args); 
} 

我已經投入了靜態輔助類的這些方法,所以實際通話稍微難看;這裏有一個例子:

ViewControl.OpenFilesetClick += (_, args) => EventHelper.Raise(OpenFilesetClick, this, args); 

(我也改名的方法來提高(),並從事件名稱被傳遞下降可選this)。

但我不完全相信,如果這是值得考慮的替代方案可以說是更容易閱讀:

ViewControl.OpenFilesetClick += (_, args) => 
{ 
    if (OpenFilesetClick != null) 
     OpenFilesetClick(this, args); 
}; 

無論如何,這是爲了更多地瞭解事件和委託是如何工作的一個有趣的方式(或他們如何不工作)。

3

編輯:好的,我想我現在明白了。其實很簡單。您應該能夠編寫代理只是一個事件,然後讓代理自己訂閱雷塞的情況下,像這樣(只是EventHandler - 我就要談這一點以後):

Proxy proxy = new Proxy(); 
raiser.SomeEvent += Proxy.Handler; 

// Then in the subscriber... 
proxy.ProxiedEvent += (whatever) 

// And the proxy class... 
public class Proxy 
{ 
    public event EventHandler ProxiedEvent; 

    public void Handler(object sender, EventArgs e) 
    { 
     EventHandler proxied = ProxiedEvent; 
     if (proxied != null) 
     { 
      // Or pass on the original sender if you want to 
      proxied(this, e); 
     } 
    } 
} 

現在,這裏的困難在於使其一般工作。我目前無法想到這樣做,儘管我現在有點分心。

這是你想到的那種東西,還是它至少可以幫助你以不同的方式思考事物?

+0

喬恩,謝謝你的回答,但作爲一個純粹的子Skeet凡人,我無法看到隱含的細節。換句話說,我迷路了。你能詳細說明一下嗎?這怎麼能適用於我的問題? –

+0

@Charles:這可能是我誤解了這個問題......我現在發現有點難以遵循,但這很可能是我自己的錯。然而,這裏的EventWrapper基本上是一種抽象「可以訂閱和取消訂閱的東西」的概念。從根本上說,這是一個事件。你不能將事件本身作爲委託,因爲它不是代表。 –

+0

我似乎有不良表達我的問題的歷史,所以我敢肯定,我應該責怪任何混亂,而不是你!基本上,我想將任何委託_dA_傳遞給一個方法,並返回一個調用_dA_的新委託_dB_,其中,如果_dA_的調用列表發生更改,我希望在調用_dB_時調用_updated_調用列表。 (我根本沒有使用過一個事件 - 只是一個代表 - 爲了證實這個問題真的是關於_delegates_的工作方式)。 –

相關問題