一、事件的本质
      
举个例子你是个取向正常的青年男性,有个身材火辣,年轻貌美,腿长肤白的美女,冲你一笑,给你讲了一个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. Mac 多个JDK的版本 脚本切换

    这里配置jdk7和jdk8版本的切换 1.官网下载jdk7和jdk8 地址:http://www.oracle.com/technetwork/java/javase/downloads 2.安装两个 ...

  2. 初识Tensorboard

    1.什么是Tensorboard? PPT设计原则中有这样一条,叫"文不如表,表不如图",可见图表在表达中更为直观.明确.程序设计中也是一样,我们经常用图表来描述程序的结构和流程, ...

  3. jQuery Ajax封装(附带加载提示和请求结果提示模版)

    1.创建HTML文件(demo) <!doctype html> <html lang="en"> <head> <meta charse ...

  4. Normalize.css源码注释翻译&浏览器css兼容问题的理解

    版本v5.0.0源码地址: https://necolas.github.io/normalize.css/5.0.0/normalize.css 翻译版: /*! normalize.css v5. ...

  5. 基于node.js制作爬虫教程

    前言:最近想学习node.js,突然在网上看到基于node的爬虫制作教程,所以简单学习了一下,把这篇文章分享给同样初学node.js的朋友. 目标:爬取 http://tweixin.yueyishu ...

  6. for循环操作数组

    if(!empty($data)){ $arr_length=count($data); //数组的步长 $array_keys_list=array_values($data); //数组的键值 f ...

  7. session或memcache过期之后跳转到登陆页面并跳出iframe框架

    <!--在你想控制跳转的页面,比如login.html中的<head>与</head>之间加入以下代码:--> <script> if (window ...

  8. Python基础-类

    Python基础-类 @(Python)[python, python基础] 写在前面 如非特别说明,下文均基于Python3 摘要 本文重点讲述如何创建和使用Python类,绑定方法与非绑定方法的区 ...

  9. MyEclipse常用操作

    选择你要注释的那一行或多行代码,按Ctrl+/即可,取消注释也是选中之后按Ctrl+/即可. 如果你想使用的快捷键的注释是的话,那么你的快捷键是ctrl+shift+/我以前都是手动注释的,直接打// ...

  10. DataFrame创建

    DataFrame/DataSet 创建 读文件接口 import org.apache.spark.sql.SparkSession val spark = SparkSession .builde ...