一、事件的本质
      
举个例子你是个取向正常的青年男性,有个身材火辣,年轻貌美,腿长肤白的美女,冲你一笑,给你讲了一个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,另外这样定义别的传递了同样消息体的事件引发类也可以复用。

看懂 ,学会 .NET 事件的正确姿势的更多相关文章

  1. 代码走查25条疑问 C# 跳转新的标签页 C#线程处理 .Net 特性 attribute 学习 ----自定义特性 看懂 ,学会 .NET 事件的正确姿势-简单版

    代码走查25条疑问   代码走查(Code Review) 是一个开发人员与架构师集中讨论代码的过程.通过代码走查可以提高代码的 质量,同时减少Bug出现的几率.但是在小公司中并没有代码走查的过程在这 ...

  2. 看懂 ,学会 .NET 事件的正确姿势-简单版

    发现之前写了一篇关于事件的阐述写的过于抽象.现在想想先理解本质由简入难比较合适  之前的一篇博客地址:https://www.cnblogs.com/LiMin/p/7212217.html 参照网上 ...

  3. 一张图看懂 JS 的事件机制

    一.为什么 JavaScript 单线程 假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准? 为了避免复杂性, JS ...

  4. 看懂此文,不再困惑于 JS 中的事件设计

    看懂此文,不再困惑于 JS 中的事件设计 今天刚在关注的微信公众号看到的文章,关于JS事件的,写的很详细也很容易理解,相关的知识点都有总结到,看完就有种很舒畅的感觉,该串起来的知识点都串起来了.反正一 ...

  5. 你真的看懂Android事件分发了吗?

    引子 Android事件分发其实是老生常谈了,但是说实话,我觉得很多人都只是懂其大概,模棱两可.本文的目的就是再次从源码层次梳理一下,重点放在ViewGroup的dispatchTouchEvent方 ...

  6. 【小白视频学Java for循环】3分钟学会Java的for循环,让看懂for循环嵌套再不是难事

    目录 一.单个for循环介绍 二.for循环嵌套 听讲时能听懂的for循环为什么一做题就晕菜?一个for循环还勉强能看懂,但为什么一看到双重for循环脑子里就感觉脑子全是浆糊? 如果有上述问题那么就继 ...

  7. 想要转行/入行做产品经理,你得先get这些正确姿势

    转自:https://mp.weixin.qq.com/s/Bh9QEihdV1JLWwB5I4VJ7Q 参考: 张小龙首次公开演讲(官方无删减版) 前腾讯高级产品经理:如何用“女性思维”做更好的产品 ...

  8. 一篇文章一张思维导图看懂Android学习最佳路线

    一篇文章一张思维导图看懂Android学习最佳路线 先上一张android开发知识点学习路线图思维导图 Android学习路线从4个阶段来对Android的学习过程做一个全面的分析:Android初级 ...

  9. angularjs 一篇文章看懂自定义指令directive

     壹 ❀ 引 在angularjs开发中,指令的使用是无处无在的,我们习惯使用指令来拓展HTML:那么如何理解指令呢,你可以把它理解成在DOM元素上运行的函数,它可以帮助我们拓展DOM元素的功能.比如 ...

随机推荐

  1. OpenGL教程(2)——第一个窗口

    OpenGL环境终于配置好了,现在我们可以开始学习OpenGL了. 首先,创建一个.cpp文件,然后打上几行#include指令: #include <iostream> using st ...

  2. 刨根究底字符编码之十二——UTF-8究竟是怎么编码的

    UTF-8究竟是怎么编码的 1. UTF-8编码是Unicode字符集的一种编码方式(CEF),其特点是使用变长字节数(即变长码元序列.变宽码元序列)来编码.一般是1到4个字节,当然,也可以更长. 为 ...

  3. vue使用Axios做ajax请求

    vue2.0之后,就不再对vue-resource更新,而是推荐使用axios 1. 安装 axios $ npm install axios 或 $ bower install axios 2. 在 ...

  4. 【WPF】用三角形网格构建三维图形

    虽然WPF只能支持部分三维模型,不过从应用功能开发的角度看,也已经够用了(非游戏开发).WPF 的三维图形,说得简单一点,也就两种而已. 1.把二维对象放到三维空间中,这个应该较为好办,像 Image ...

  5. 每天一个JS 小demo之“随机”抽奖。主要知识点:Math函数,数组方法,递归

    <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"& ...

  6. Buffer深入分析

    Buffer Buffer的类图如下: 除了Boolean,其他基本数据类型都有对应的Buffer,但是只有ByteBuffer才能和Channel交互.只有ByteBuffer才能产生Direct的 ...

  7. 纯css实现横向下拉菜单

    自己最近在捣腾css代码,不光是js能做很多有趣的东西,这货也可以做很多东西,现在把自己的一些作品分享给大家. 做得有点粗糙,大家根据这个思路来,可以自己修改修改. 关于demo:这是一个横向下拉的菜 ...

  8. 【原创】Ajax的用法总结

    一.什么是Ajax Ajax英文全称为“ Asynchr JavsScript and XML”(异步的JavaScript和XML),是一种创建 交互式网页的开发技术. 二.Ajax技术的核心 Aj ...

  9. Webpack 开发工具与模块热替换

    Webpack 开发工具与模块热替换 ​⚠️ 注意: 永远不要在生产环境中使用这些工具,永远不要. devtool 当 JavaScript 异常抛出时,你常会想知道这个错误发生在哪个文件的哪一行.然 ...

  10. Java(17)异常

    一.异常 1.1程序执行过程中出现的影响程序运行正常运行的现象.  1.2异常语法 try{ //代码块 }catch(异常类型 e){ }catch(异常类型 e){ }...{ }finally{ ...