• C#事件


    转自:http://www.cnblogs.com/michaelxu/archive/2008/04/02/1134217.html

    事件是一种特殊的委托

    运行机制是:注册---触发 ---处理

    签名就是把函数名字去掉以后剩下的东西(返回值、参数、调用方式等)

    C#中使用事件需要的步骤:
    1.创建一个委托
    2.将创建的委托与特定事件关联(.Net类库中的很多事件都是已经定制好的,所以他们也就有相应的一个委托,在编写关联事件处理程序--也就是当有事件发生时我们要执行的方法的时候我们需要和这个委托有相同的签名)
    3.编写事件处理程序
    4.利用编写的事件处理程序生成一个委托实例
    5.把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件

    C#中事件产生和实现的流程:
    1.定义A为产生事件的实例,a为A产生的一个事件
    2.定义B为接收事件的实例,b为处理事件的方法
    3.A由于用户(程序编写者或程序使用者)或者系统产生一个a事件(例如点击一个Button,产生一个Click事件)
    4.A通过事件列表中的委托对象将这个事件通知给B
    5.B接到一个事件通知(实际是B.b利用委托来实现事件的接收)
    6.调用B.b方法完成事件处理

        public class A
        {
            public delegate void EventHandler(object sender); //创建委托
            public event EventHandler a;    //将创建的委托与特定事件关联
    
            public void Run()     //事件处理程序
            {
                Console.WriteLine("Trigger an event.");
                a(this);  //利用编写的事件处理程序生成一个委托实例
            }
        }
    
        class B
        {
            public B(A a)
            {
                a.a += new A.EventHandler(this.b);  //把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件
            }
            private void b(object sender)
            {
                Console.WriteLine("Received and handled an event." );
                Console.Read();
            }
        }
    

     例子:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;

    namespace EventDemo
    {
    public delegate void SalaryCompute(object sender,MyEventArgs e); //声明一个代理类

    public class Employee
    {
    public event SalaryCompute OnSalaryCompute; //定义事件,将其与代理绑定

    public virtual void FireEvent(MyEventArgs e) //触发事件的方法
    {

    if (OnSalaryCompute != null)
    {
    OnSalaryCompute(this,e); //触发事件
    }

    }
    }

    public class MyEventArgs : EventArgs //定义事件参数类
    {

    public readonly double _salary;
    public MyEventArgs(double salary)
    {
    this._salary = salary;
    }
    }

    public class HumanResource
    {
    public void SalaryHandler(object sender,MyEventArgs e) //事件处理函数,其签名应与代理签名相同
    {

    Console.WriteLine("Salary is {0}",e._salary); //只是打印一行字而已
    }


    public static void Main()
    {
    Employee ep = new Employee();
    HumanResource hr = new HumanResource();
    MyEventArgs e = new MyEventArgs(123.40);
    ep.OnSalaryCompute+=new SalaryCompute(hr.SalaryHandler); //注册
    for (; ; )

    {
    Thread.Sleep(1000); //让程序“睡”一秒
    ep.FireEvent(e); //触发事件
    }

    //Console.Read();
    }

    }
    }

    我们要注意的一个地方就是事件处理函数的签名要和代理的签名一致

    下面在给个列子:

    using System;

    namespace Vczx.ProCSharp.Event
    {
    /// <summary>
    /// 类EatEventArgs 必须继承自类EventArgs,用来引发事件时封装数据
    /// </summary>
    public class EatEventArgs : EventArgs

    {
    public String restrauntName; //饭店名称
    public decimal moneyOut; //准备消费金额
    }


    /// <summary>
    /// 这个委托用来说明处理吃饭事件的方法的方法头(模式)
    /// </summary>
    public delegate void EatEventHandler(object sender, EatEventArgs e);


    /// <summary>
    /// 引发吃饭事件(EateEvent)的类Master(主人),这个类必须
    /// 1.声明一个名为EatEvent的事件: public event EatEventHandler EatEvent;
    /// 2.通过一个名为OnEatEvent的方法来引发吃饭事件,给那些处理此事件的方法传数据;
    /// 3.说明在某种情形下引发事件呢?在饿的时候。用方法Hungrg来模拟。
    /// </summary>
    public class Master

    {
    //声明事件
    public event EatEventHandler EatEvent;


    //引发事件的方法
    public void OnEatEvent(EatEventArgs e)

    {
    if (EatEvent != null)
    {
    EatEvent(this, e);
    }
    }

    //当主人饿的时候,他会指定吃饭地点和消费金额。
    public void Hungry(String restrauntName, decimal moneyOut)

    {
    EatEventArgs e = new EatEventArgs();
    e.restrauntName = restrauntName;
    e.moneyOut = moneyOut;

    Console.WriteLine("主人说:");
    Console.WriteLine("我饿了,要去{0}吃饭,消费{1}元", e.restrauntName, e.moneyOut);

    //引发事件
    OnEatEvent(e);

    }
    }

    /// <summary>
    /// 类Servant(仆人)有一个方法ArrangeFood(安排食物)来处理主人的吃饭事件
    /// </summary>
    public class Servant

    {
    public void ArrangeFood(object sender, EatEventArgs e)
    {
    Console.WriteLine();
    Console.WriteLine("仆人说:");
    Console.WriteLine("我的主人, 您的命令是 : ");
    Console.WriteLine("吃饭地点 -- {0}", e.restrauntName);
    Console.WriteLine("准备消费 -- {0}元 ", e.moneyOut);
    Console.WriteLine("好的,正给您安排。。。。。。。。\n");
    System.Threading.Thread.Sleep( 5000 );
    Console.WriteLine("主人,您的食物在这儿,请慢用");
    Console.Read();
    }
    }

    /// <summary>
    /// 类God安排qinshihuang(秦始皇)的仆人是lisi(李斯),并让李斯的ArrangeFood
    /// 方法来处理qinshihuang的吃饭事件:qinshihuang.EatEvent += new EatEventHandler(lishi.ArrangeFood);
    /// </summary>
    public class God

    {
    public static void Start()
    {
    Master qinshihuang = new Master();
    Servant lishi = new Servant();

    qinshihuang.EatEvent += new EatEventHandler(lishi.ArrangeFood);

    //秦始皇饿了,想去希尔顿大酒店,消费5000元
    qinshihuang.Hungry("希尔顿大酒店", 5000.0m);

    }
    }
    }

    输出:

    主人说:
    我饿了,要去希尔顿大酒店吃饭,消费5000.0元

    仆人说:
    我的主人, 您的命令是 :
    吃饭地点 -- 希尔顿大酒店
    准备消费 -- 5000.0元
    好的,正给您安排。。。。。。。。

    主人,您的食物在这儿,请慢用




  • 相关阅读:
    IdentityServer4学习笔记
    常用链接地址
    c++ 多线程(2000个)端口扫描(附源码)
    C++ 定时器Timer在项目中的使用
    [Under the hood]---Matt Pietrek October 1996 MSJ
    [under the hood]Reduce EXE and DLL Size with LIBCTINY.LIB
    TN035: Using Multiple Resource Files and Header Files with Visual C++
    单文件版本的netframework的net core 2.1
    Dependency Walker的替代品Dependencies
    怎么使用gradle给spring 打thinjar(gradle 7)
  • 原文地址:https://www.cnblogs.com/irelands/p/2408252.html
Copyright © 2020-2023  润新知