2013-04-12 102 views
1

我想創建一個流利的擴展方法來訂閱(並且不太重要的是取消訂閱)事件。這是地方的+= new Eventhandler(Method)訂閱/取消訂閱(添加/刪除)到擴展方法內部的事件

與使用.RespondBy(Method)延長我想這樣做:object.WhenSomethingChanges.RespondBy(DoingThisOtherThing);

取而代之的是:object.WhenSomethingChanges += new EventHandler(DoingThisOtherThing);

我做了一堆google搜索的,雖然我沒有完全掌握複雜的細節,我現在明白,這與你是否訪問本地領域或公共事件有關。

就這樣說,我只是在關注「如何」這可以做,而不關心「爲什麼」我的第一次嘗試沒有奏效。如果不解決方法,至少一個明確的 「你不能做到這一點......在所有的,直到永遠。」 也將是有用的信息...

CommuncationsStatusPresenter (Image)

Image of attempted usage, does not compile

CommuncationsStatusPresenter(代碼)

using System; 
using InspectionStation.Models; 
using InspectionStation.Views; 
using MachineControl.OPC; 

namespace InspectionStation.Presenters 
{ 
    public class CommuncationsStatusPresenter 
    { 
     // Fields 
     private ICommunicationsModel m_model; 
     private ICommunicationsView m_view; 

     // Constructor 
     public CommuncationsStatusPresenter 
      (ICommunicationsModel p_model, ICommunicationsView p_view) 
     { 
      m_model = p_model; 
      m_view = p_view; 
      HookEvents(); 
     } 
     private void HookEvents() 
     { 
      m_model 
       .When_Communications_Pulses_Heartbeat 
       .RespondBy(Setting_the_state_of_an_Indicator); 
     } 

     // Eventhandler 
     void Setting_the_state_of_an_Indicator(Tag sender, EventArgs e) 
     { 
      bool State = sender.BooleanValue; 
      m_view.Set_Communications_Status_Indicator = State; 
     } 
    } 
} 

RespondBy

using System; 

namespace Common.Extensions 
{ 
    public static partial class ExtensionMethods 
    { 
     public static 
      void RespondBy<TSender, TEventArgs>(this 
      GenericEventHandler<TSender, TEventArgs> p_event, 
      GenericEventHandler<TSender, TEventArgs> p_handler 
      ) where TEventArgs : EventArgs 
     { 
      p_event += new GenericEventHandler<TSender, TEventArgs>(p_handler); 
     } 
    } 
} 

GenericEventHandler

using System; 

namespace Common 
{ 
    [SerializableAttribute] 
    public delegate void GenericEventHandler<TSender, TEventArgs> 
     (TSender sender, TEventArgs e) 
     where TEventArgs : EventArgs; 
} 

ICommunicationsModel

using System; 
using Common; 
using MachineControl.OPC; 

namespace InspectionStation.Models 
{ 
    public interface ICommunicationsModel 
    { 
     event GenericEventHandler<Tag, EventArgs> 
      When_Communications_Pulses_Heartbeat; 
    } 
} 

ICommunicationsView

namespace InspectionStation.Views 
{ 
    public interface ICommunicationsView 
    { 
     bool Set_Communications_Status_Indicator { set; } 
    } 
} 

回答

1

因爲C#編譯器嚴格要求的事件使用外必須後跟一個+=-=,用於處理程序的安裝和拆卸的命令,它不會是可能延長,並使用此以外的班上。

但是,如果你願意的基礎上的類本身更具體的方法,如:

object.RespondWhenSomethingChangesBy(DoingThisOtherThing); 

那麼你可以,這個方法裏面,利用因爲類中定義的事件的擴展方法。我知道這意味着你會建立大量的鍋爐板代碼的事件,但如果這是你真正想要的,則上述可能被認爲是更精簡比:

object.WhenSomethingChanges.RespondBy(DoingThisOtherThing); 

我這樣做完全瞭解你在這裏的位置,並希望微軟選擇允許將來擴展事件(我可以想到一些有趣的理由我會使用它),但在那之前,我想我們只需要解決它。老實說,我相信有一些非常好的理由它並沒有在第一時間得到實施,微軟在思考這些事情方面做得非常好。

+0

那麼,這似乎足夠明確!謝謝:) – HodlDwon

+0

嗯...這看起來很有希望,儘管潛在更多的努力比收益http://stackoverflow.com/questions/18385967/c-sharp-event-keyword-advantages基本上這個想法是短路標準的'事件'關鍵字修飾符,並手動通過代理/操作自由地高興。我沒有嘗試過實現這個,鏈接中沒有例子,但所有的部分似乎都在那裏,使我的原始問題有一個可能的(雖然不是推薦)的解決方案。我會在某個時候重新審視這個問題,看看我是否可以得到一個優雅的實現,即使它只是踢。 – HodlDwon

1

鑑於Michael Perrenoud的回答,我已經解決做好以下工作作爲我的模式的一部分......

public class CommuncationsStatusPresenter 
    { 
     ... 

     private void HookEvents() 
     { 
      m_model. 
       When_Communications_Pulses_Heartbeat += new EventHandler<Tag, EventArgs>(
       Set_the_state_of_an_Indicator); 
     } 

     // Eventhandler 
     void Set_the_state_of_an_Indicator(Tag sender, EventArgs e) 
     { 
      ... 
     } 
    } 
} 

沒什麼特別的...只是conistent自動格式化基礎上新的生產線,但似乎在這個時候成爲最好的解決方案(即我可以幾乎朗讀代碼以快速辨別其意圖而不訴諸廣泛的評論描述)。

注意:我改名爲長GenericEventHandler簡單EventHandler因爲沒有太多需要一個特別的名字。