事件

发布者和订阅者

发布者:发布某个事件的类或结构,其他类可以在该事件发生时得到通知。
订阅者:注册并在事件发生时得到通知的类或结构
事件处理程序:由订阅者注册到事件的方法,在发布者触发事件时执行。
触发事件:当事件触发时,所有注册到它的方法都会被依次调用。
对事件我们只可以添加、删除、或调用事件处理程序。

源代码组件概览

委托类型声明
事件处理程序声明
事件声明
事件注册触发事件的代码

声明事件

事件声明在一个类中。
需要委托类型的名称,任何附加到事件的处理程序都必须都必须与委托类型的签名和返回类型匹配。
声明为public。这样其他类和结构可以在它上面注册事件处理程序。
不能使用对象创建表达式(new)来创建它的对象。
public event EventHandler CountedADozen;
关键字+委托类型+事件名
public event EventHandler MyEvent1,MyEvent2,MyEvent3;
声明三个事件
public static event EventHandler CountedADozen;
静态事件

事件是成员

事件是类或结构的成员所以不能在一段可执行代码中声明事件
它必须声明在类或结构中,和其他成员一样。
事件成员被隐式初始化为null

订阅事件

订阅者向事件添加剂事件处理程序。
事件处理程序必须具有与事件的委托相同的返回类型和签名

    //添加四种方法
    //incrementer.CounterADozen += IncrementerDozensCount;//实例方法
    //incrementer.CounterADozen += ClassB.CountHandelerB;//静态方法
    //mc.CounterAdozen += new EventHandler(cc .CounterHandlerC);//委托形式
    //incrementer.CounterAdozen += () => DozensCount++;//Lambda表达式
    //incrementer.CounterAdozen += delegate { DozensCount++; };//匿名方法

触发事件

事件成员本身只是保存了需要被调用的事件处理程序。
在触发事件前与null比较。
触发事件的语法和调用方法一样。

delegate void Handler();//声明委托
//发布者
class Incrementer
{
    public event Handler CounterADozen;//创建事件事件并发布
    public  void DoCount() 
    {
        for (int i = 1; i < 100; i++)
            if (i % 12 == 0&&CounterADozen != null)//确认有方法可以执行
                    CounterADozen();//每增加12个计数触发事件一次
    }
}
//订阅者
class Dozens
{
    public int DozensCount { get; private set; }
    public Dozens(Incrementer incrementer)
    {
        DozensCount = 0;
        //incrementer.CounterADozen += IncrementerDozensCount;//订阅事件
        incrementer.CounterADozen += () => DozensCount++ ;
    }
    //void IncrementerDozensCount()
    //{
    //    DozensCount++;
    //}
}
class Program
{
    static void Main(string[] args)
    {
        Incrementer incrementer = new Incrementer();
        Dozens dozensCounter = new Dozens(incrementer );
        incrementer.DoCount();
        Console.WriteLine("Number of dozens={0}", dozensCounter.DozensCount);
        Console.ReadKey();
    }
}

标准事件的用法

对于事件的用法.net框架提供了一个标准模式。
使用EventHandler委托类型。
public delegate void EventHandler(object sender,EventArgs e);
第一个参数用来保存触发事件的对象的引用。
第二个参数用来保存状态信息。
返回类型是void。
EventArgs不能传递任何数据。如果要传,需声明派生自 EventArgs的类。

class Incrementer//发布者
{
    public event EventHandler CounterADozen;//使用系统定义的EventHandler委托
    public void DoCount()
    {
        for (int i = 1; i < 100; i++)
            if (i % 12 == 0 && CounterADozen != null)
                CounterADozen(this,null);//触发事件时使用Event Handler的参数
    }
}
//订阅者
class Dozens
{
    public int DozensCount { get; private set; }
    public Dozens(Incrementer incrementer)
    {
        DozensCount = 0;
        //incrementer.CounterADozen += IncrementerDozensCount;
        incrementer.CounterADozen += delegate(object source, EventArgs e) { DozensCount++; };
    }
    //void IncrementerDozensCount(object source, EventArgs e)
    //{
    //    DozensCount++;
    //} 
}
class Program
{
    static void Main(string[] args)
    {
        Incrementer incrementer = new Incrementer();
        Dozens dozensCounter = new Dozens(incrementer);
        incrementer.DoCount();
        Console.WriteLine("Number of dozens={0}", dozensCounter.DozensCount);
        Console.ReadKey();
    }
}

通过扩展EventArgs来传递数据

需声明一个派生自 EventArgs的自定义类。
使用新自定义的委托类型(泛型委托)

public class IncrementerEventArgs : EventArgs//自定义类派生自EventArgs
{
    public int IterationCount { get; set; }//存储整数
}
class Incrementer
{
    public event EventHandler<IncrementerEventArgs> CounterADozen;//泛型委托使用自定义类
    public void DoCount()
    {
        IncrementerEventArgs args = new IncrementerEventArgs();//自定义类对象
        for (int i = 1; i < 100; i++)
            if (i % 12 == 0 && CounterADozen != null)
            {
                args.IterationCount = i;
                CounterADozen(this, args);//触发事件时传递参数
            }
    }
}
class Dozens
{
    public int DozensCount { get; private set; }
    public Dozens(Incrementer incrementer)
    {
        DozensCount = 0;
        incrementer.CounterADozen += IncrementerDozensCount;
    }
    void IncrementerDozensCount(object source, IncrementerEventArgs e)
    {
        Console.WriteLine("Incrementer at iteration:{0} in {1}", e.IterationCount, source.ToString());
        DozensCount++;
    }
    class Program
    {
        static void Main(string[] args)
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozensCounter = new Dozens(incrementer);
            incrementer.DoCount();
            Console.WriteLine("Number of dozens={0}", dozensCounter.DozensCount);
            Console.ReadKey();
        }
    }
}

移除事件处理程序

如果一个处理程序向事件注册了很多次,那么当执行命令移除处理程序时,将只移除列表中该程序的最后一个实例

class Publisher
{
    public event EventHandler SimpleEvent;
    public void RaiseTheEvent()
    {
        SimpleEvent(this ,null);
    }
}
class Subscriber
{
    public void MethodA(object o, EventArgs e) { Console.WriteLine("AAA"); }
    public void MethodB(object o, EventArgs e) { Console.WriteLine("BBB"); }
    public void MethodC(object o, EventArgs e) { Console.WriteLine("CCC"); }
}
class Program
{
    static void Main(string[] args)
    {
        Publisher p = new Publisher();
        Subscriber s = new Subscriber();
        p.SimpleEvent += s.MethodA;
        p.SimpleEvent += s.MethodB;
        p.SimpleEvent += s.MethodC;
        p.RaiseTheEvent();
        Console.WriteLine("\r\nRemove MethodB");
        p.SimpleEvent -= s.MethodB;
        p.RaiseTheEvent();
        Console.ReadKey();
    }
}

事件访问器

要改变+=或-=这两个运算符的操作,可以为事件定义事件访问器

public event EventHandler CountADozen
{
    add
    {
        //执行+=运算符的代码
    }
    remove
    { 
        //执行-=运算符的代码
    }
}

声明事件访问器后,事件不包含任何内嵌委托对象,必须实现自己的机制来存储和移除事件注册的方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值