簡體   English   中英

引發事件的模式

[英]Pattern for Raising Events

我有一個抽象類 A,它具有檢查閾值所需的功能。 當違反閾值時,我希望引發一個事件,說通知我。 我在 Qt 中做過很多次這種事情,但我似乎無法弄清楚如何將它轉移到 C#。 這是我目前想到的結構。

namespace N
{
  abstract class A
  {
    public delegate void Notify();
    public event Notify Notifier;
    public abstract void CheckThreshold();
  }

  class B : A
  {
    public override void CheckThreshold()
    {
       Notifier();
    }
  }

  class N
  {
    public AlertMe()
    {
    }
    public static Main()
    {
      var b = new B();
      b.Notifier += new A.Notify(AlertMe);

      b.CheckThreshold();
    }
  }
}

通常,您要遵循的表格是這樣的:

public event EventHandler<SomeEventArgs> SomeEvent = (s, e) => { };

protected virtual void OnSomeEvent(SomeEventArgs e)
{
    SomeEvent(this, e);
}

所以在你的情況下,你可能想要:

abstract class A {

    public event EventHandler<EventArgs> ThresholdExceeded = (s, e) => { };

    protected virtual void OnThresholdExceeded(EventArgs e)
    {
        ThresholdExceeded(e);
    }

    public abstract void CheckThreshold();
}

class B : A {
    public override void CheckThreshold()
    {
        if (/* your condition */) OnThresholdExceeded(new EventArgs());
    }
}

現在有一些事情 - EventHandler 類型是一些很好的語法糖,用於制作特定類型的事件。 右側的 lambda 表達式將其初始化為默認處理程序,因此您不必在調用它之前檢查它是否為 null。

EventArgs 是特定於事件的信息 - 您沒有,但如果您有,您可以將 EventArgs 子類化並放入您的事件接收器需要的任何數據。

Microsoft 為 .NET 中的事件規定了public event SomeEventNameprotected virtual void OnSomeEvent對的模式。 不必遵循這一點,但它是.NET程序員想要的。

您可以在基類 A 中定義一個輔助方法

protected void FireNotification() 
{
    if (Notifier != null)
        Notifier();
}

並從覆蓋的CheckTreshold調用它。

這段代碼有幾個問題。

首先,您應該使用 EventHandler 內置委托來定義事件。 其次,您不能在定義它的類之外引發事件(這就是您不能使用后代的 Notify() 的原因)。 第三,你可以使用模板方法設計模式,更清楚地定義你的基類和它的后代之間的契約,並實現閾值檢查的一部分。

最后我完全不明白為什么你需要繼承層次結構? 也許您可以在一個類中實現所有必需的邏輯? 但無論如何,這里的代碼可以正確編譯和運行:

  abstract class A
  {
    // Avoid defining custom delegate at all because there is a lot of 
    // build-in events for every case, like EventHandler<T>, 
    // Func<T>, Action<T> etc
    // public delegate void Notify();
    public event EventHandler ThreasholdViolated;

    protected void OnThreasholdViolated()
    {
       var handler = ThreasholdViolated;
       if (handler != null)
         handler(this, EventArgs.Empty);
    }

    public abstract void CheckThreshold();
  }

  class B : A
  {
    public override void CheckThreshold()
    {
       OnThreasholdViolated();
    }
  }

通常的模式是在基類中提供受保護的虛擬方法,如http://msdn.microsoft.com/en-us/library/vstudio/9aackb16(v=vs.100).aspx所示。 該方法的名稱約定是 On[EventName] 並采用事件 args 實例。

還要遵循使用 EventHandler 或 EventHandler 作為委托的約定,並提供事件發起者和相應的參數。 您可以在http://msdn.microsoft.com/en-us/library/vstudio/ms229011(v=vs.100).aspx 中找到更多相關信息。 請注意,來自 MSDN 的示例並未遵循所有這些約定。

public abstract class A
{
    public EventHandler<EventArgs> OnThresholdViolated;

    public abstract void CheckThreshold();
}

public class B : A
{
    public B(EventHandler<EventArgs> alertMe) {
        OnThresholdViolated += alertMe;
    }

    public override void CheckThreshold()
    {
        if (null != OnThresholdViolated)
        {
            OnThresholdViolated(this, EventArgs.Empty);
        }
    }
}

然后調用使用:

        B b = new B(AlertMe);

        b.CheckThreshold();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM