如何在C#中分派事件

21

我希望创建自己的事件并分派它们。 在C#中我以前没有做过这个,只在Flex中尝试过.. 我猜应该会有很多不同之处。

有人可以提供一个好的例子吗?


1
WinForms、WebForms、ASP.NET MVC还是WPF? - Oded
谢谢大家的回复!!它们都帮助了我;) 再次感谢!! - Janov Byrnisson
4个回答

49

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

这里是一个基于最简单的事件委托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开始,在“Trigger”方法中调用代码变得更加容易,使用空值条件运算符?.可以缩短空值测试而不进行复制,同时保持线程安全性:

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

1
是的,虽然您会使用EventHandler<T>,其中T是您的事件参数类型,也就是:public event EventHandler<MyOwnEventArgs> MyEvent; - Sekhat
1
这也是一个.NET常见的做法,即您的自定义EventArgs类继承自EventArgs。 - Sekhat
只是一个快速问题。我可以使用这个事件结构创建可插拔架构吗? - AjmeraInfo
@AjmeraInfo - 是的,你可以这样做,但这不是唯一的解决方案。确保你也了解 interface - H H
@HenkHolterman 非常感谢您的快速回复。您能指导我从哪里开始吗?有什么参考样例项目吗? - AjmeraInfo
显示剩余4条评论

3

C#中的事件使用委托(delegate)。

public static event EventHandler<EventArgs> myEvent;

static void Main()
{
   //add method to be called
   myEvent += Handler;

   //call all methods that have been added to the event
   myEvent(this, EventArgs.Empty);
}

static void Handler(object sender, EventArgs args)
{
  Console.WriteLine("Event Handled!");
}

3

使用典型的.NET事件模式,假设您在事件中不需要任何特殊参数。您典型的事件和分发模式如下所示。

public class MyClassWithEvents
    {
        public event EventHandler MyEvent;

        protected void OnMyEvent(object sender, EventArgs eventArgs)
        {
            if (MyEvent != null)
            {
                MyEvent(sender, eventArgs);
            }
        }

        public void TriggerMyEvent()
        {
            OnMyEvent(sender, eventArgs);
        }
    }

将某些内容与事件关联起来可以非常简单,例如:
public class Program
{
    public static void Main(string[] args)
    {
        MyClassWithEvents obj = new MyClassWithEvents();

        obj.MyEvent += obj_myEvent;
    }

    private static void obj_myEvent(object sender, EventArgs e)
    {
        //Code called when my event is dispatched.
    }
}

请查看此 MSDN 页面上的链接。


0

看一下'委托'

  • 定义一个委托
  • 将委托类型用作字段/属性(添加“Event”关键字)
  • 现在您正在公开用户可以使用“+= MyEventMethod;”连接到的事件

希望这有所帮助,


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接