看懂 ,学会 .NET 事件的正确姿势

一、事件的本质
      
举个例子你是个取向正常的青年男性,有个身材火辣,年轻貌美,腿长肤白的美女,冲你一笑,给你讲了一个ABCD羊吃草的故事。你有什么反应?
可能你关注点在于颜值,身材,故事,故事含义。后续事情?OK,这些都没毛病。和事件有什么关系呢?以上你关注的所有东西都可以概括为信息-事件。
她发出了一个信息,你做出了反应。 那么整个事件的运行机制就完成了。
   简单的说就是 :一个对象发出消息,另外的对象做出响应。
   如图:

   那么再具体的详细的讲解不如Show Code :上代码:
  

//如果本篇幅过于难以理解那么,https://www.cnblogs.com/LiMin/p/10364867.html 这个是简单版本的可以帮助你先快速理解
namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            PLMM plmm = new PLMM();//漂亮妹妹
            DS ds = new DS();//屌丝
            GFS gfs = new GFS();//高富帅
            MsgEventArgs msg = new MsgEventArgs
            {
                MsgFrom = "美女",
                MsgTo = "取向正常的男性",
                MsgContent = "冲你笑,讲羊吃草故事。"
            };
            msg.Register(plmm, ds, gfs);//注册
            plmm.SendMsg(msg);//发送
            Console.ReadLine();
        }
    }
    #region 收发事件消息接口

    /// <summary>
    /// 程序角度:事件的定义是:public delegate EventHandler<TEventArgs>(object sender, TEventArgs e);
    /// 因此:事件的接受者必须具有:void Method(object sender,TEventArgs e) 形式
    /// sender :事件的发起者
    /// TEventArgs:是事件消息体
    /// 所以接受方需要接受这 2个参数,而发送方只需要发送 消息体
    /// </summary>
    public interface IBaseEvent
    {
        event EventHandler<MsgEventArgs> MsgEvent;

        /// <summary>
        /// 时间的信息
        /// </summary>
        /// <param name="msgEventArgs"></param>
        void SendMsg(MsgEventArgs msgEventArgs);
    }

    /// <summary>
    /// 程序角度:事件的定义是:public delegate EventHandler<TEventArgs>(object sender, TEventArgs e);
    /// 因此:事件的接受者必须具有:void Method(object sender,TEventArgs e) 形式
    /// sender :事件的发起者
    /// TEventArgs:是事件消息体
    /// 所以接受方需要接受这 2个参数,而发送方只需要发送 消息体
    /// </summary>
    public interface IReceive
    {
        void ReceiveMsg(object sender, MsgEventArgs msgEventArgs);
    }

    #endregion

    #region 消息发布者
    public class PLMM : IBaseEvent
    {
        public event EventHandler<MsgEventArgs> MsgEvent;

        /// <summary>
        /// 负责引发事件的方法
        /// </summary>
        /// <param name="msgEventArgs"></param>
        public void SendMsg(MsgEventArgs msgEventArgs)
        {
            Console.WriteLine("身材火辣,年轻,腿长,肤白貌美的美女开始行动:{0}", msgEventArgs.MsgContent);
            Dosomething(MsgEvent, msgEventArgs);
        }
        /// <summary>
        /// 如果以PLMM 为基类可以复写该方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="msgEventArgs"></param>
        protected virtual void Dosomething(object sender, MsgEventArgs msgEventArgs)
        {
            EventHandler<MsgEventArgs> temp = Volatile.Read(ref MsgEvent);
            temp?.Invoke(this, msgEventArgs);
        }
    }

    #endregion

    #region 消息订阅者
    /// <summary>
    /// 程序角度:事件的定义是:public delegate EventHandler<TEventArgs>(object sender, TEventArgs e);
    /// 因此:事件的接受者必须具有:void Method(object sender,TEventArgs e) 形式
    /// sender :事件的发起者
    /// TEventArgs:是事件消息体
    /// </summary>
    public class DS : IReceive
    {
        public void ReceiveMsg(object sender, MsgEventArgs msgEventArgs)
        {
            Console.WriteLine("屌丝收到:{0}{1}。反应:受不了,得去补充营养了。", msgEventArgs.MsgFrom, msgEventArgs.MsgContent);
        }
    }
    /// <summary>
    /// 程序角度:事件的定义是:public delegate EventHandler<TEventArgs>(object sender, TEventArgs e);
    /// 因此:事件的接受者必须具有:void Method(object sender,TEventArgs e) 形式
    /// sender :事件的发起者
    /// TEventArgs:是事件消息体
    /// </summary>
    public class GFS : IReceive
    {
        public void ReceiveMsg(object sender, MsgEventArgs msgEventArgs)
        {
            Console.WriteLine("高富帅收到:{0}{1}。反应:I Need You!!!", msgEventArgs.MsgFrom, msgEventArgs.MsgContent);
        }
    }

    #endregion

    #region 事件成员-消息类
    /// <summary>
    /// 事件成员:事件的附加信息。
    /// 程序角度:事件的定义是:delegate EventHandler<TEventArgs>(object sender, TEventArgs e);
    /// 按照约定事件附加信息即消息类必须实现:EventArgs 类,
    /// </summary>
    public class MsgEventArgs : EventArgs
    {
        public string MsgFrom { get; set; }
        public string MsgTo { get; set; }
        public string MsgContent { get; set; }
        public void Register(IBaseEvent baseEvent, params IReceive[] action)
        {
            foreach (var item in action)
            {
                if (item != null)
                {
                    baseEvent.MsgEvent += item.ReceiveMsg;
                }
            }
        }
    }

    #endregion


}

总结:定义事件的步骤:
一.定义类型来容纳所有需要发送给事件通知接收者的附加信息。
二.定义事件成员
三.定义负责引发事件的方法来通知事件的登记对象。
四.定义方法将输入转化为期望事件

 PS:程序Demo仅仅作为演示,其中有几处设计的不是很好。。。。。。。

 综上:事件 EventHandler<TEventArgs> 系统定义:事件是由一个对象引发因此,第一个参数为 Object ,第二个为事件消息体 TEventArgs。
public delegate EventHandler<TEventArgs>(object sender, TEventArgs e); 
1.因此事件接受方的,方法必须满足:void Method(object sender,TEventArgs e) 形式 因为事件定义如此
2.按照约定:事件的消息体必须继承自:EventArgs
3.事件就是一个方法的注册列表,可以添加,也可以删除,本例没有删除事件,自己实现吧。
4.事件引发方法,必须有消息体。
疑惑解析:EventHandler<TEventArgs>(object sender, TEventArgs e); 第一个参数之所以是 Object 是因为,事件引发的类型可以作为基类,被实现。要是要求由子类来引发事件,那么需要类型转化,因此定义为Object,另外这样定义别的传递了同样消息体的事件引发类也可以复用。

原文地址:https://www.cnblogs.com/LiMin/p/7212217.html