• 看懂 ,学会 .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,另外这样定义别的传递了同样消息体的事件引发类也可以复用。

  • 相关阅读:
    【Dubbo 源码解析】08_Dubbo与Spring结合
    【Dubbo 源码解析】07_Dubbo 重试机制
    【Dubbo 源码解析】06_Dubbo 服务调用
    【Dubbo 源码解析】05_Dubbo 服务发现&引用
    【Dubbo 源码解析】04_Dubbo 服务注册&暴露
    【Dubbo 源码解析】03_Dubbo Protocol&Filter
    【Dubbo 源码解析】02_Dubbo SPI
    Hadoop(十五)MapReduce程序实例
    Hadoop(十四)MapReduce原理分析
    Hadoop(十三)分析MapReduce程序
  • 原文地址:https://www.cnblogs.com/LiMin/p/7212217.html
Copyright © 2020-2023  润新知