小编典典

如何在C#中调度事件

c#

我希望创建自己的事件并进行调度。我以前从来没有在C#中做到这一点,而只是在Flex中做到了。我猜必须存在很多差异。

谁能给我一个好榜样?


阅读 470

收藏
2020-05-19

共1个答案

小编典典

在所有库类中都有一种模式。建议您也为自己的类使用,特别是对于框架/库代码。但是当您偏离或跳过一些步骤时,没有人会阻止您。

这是基于最简单的事件委托的示意图System.Eventhandler

// The delegate type. This one is already defined in the library, in the System namespace
// the `void (object, EventArgs)` signature is also the recommended pattern
public delegate void Eventhandler(object sender, Eventargs args);

// your publishing class
class Foo  
{
    public event EventHandler Changed;    // the Event

    protected virtual void OnChanged()    // the Trigger method, called to raise the event
    {
        // make a copy to be more thread-safe
        EventHandler handler = Changed;

        if (handler != null)
        {
            // invoke the subscribed event-handler(s)
            handler(this, EventArgs.Empty);  
        }
    }

    // an example of raising the event
    void SomeMethod()
    {
       if (...)        // on some condition
         OnChanged();  // raise the event
    }
}

以及如何使用它:

// your subscribing class
class Bar
{       
    public Bar()
    {
        Foo f = new Foo();
        f.Changed += Foo_Changed;    // Subscribe, using the short notation
    }

    // the handler must conform to the signature
    void Foo_Changed(object sender, EventArgs args)  // the Handler (reacts)
    {
        // the things Bar has to do when Foo changes
    }
}

当您有信息要传递时:

class MyEventArgs : EventArgs    // guideline: derive from EventArgs
{
    public string Info { get; set; }
}

class Foo  
{
    public event EventHandler<MyEventArgs> Changed;    // the Event
    ...
    protected virtual void OnChanged(string info)      // the Trigger
    {
        EventHandler handler = Changed;   // make a copy to be more thread-safe
        if (handler != null)
        {
           var args = new MyEventArgs(){Info = info};  // this part will vary
           handler(this, args);  
        }
    }
}

class Bar
{       
   void Foo_Changed(object sender, MyEventArgs args)  // the Handler
   {
       string s = args.Info;
       ...
   }
}

更新资料

从C#6开始,“触发器”方法中的调用代码变得更加容易,可以使用空条件运算符来缩短空测试,?.而无需在保持线程安全的情况下进行复制:

protected virtual void OnChanged(string info)   // the Trigger
{
    var args = new MyEventArgs{Info = info};    // this part will vary
    Changed?.Invoke(this, args);
}
2020-05-19