一、事件的本质
      
举个例子你是个取向正常的青年男性,有个身材火辣,年轻貌美,腿长肤白的美女,冲你一笑,给你讲了一个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. python unittest 测试笔记(一)

    测试最基本的原理就是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败. python 单元测试官方文档: [Python: 2.7] (https://docs.python.or ...

  2. 我做的第一个程序(菜鸟的java课堂笔记)

    内存: 堆区,栈区,常量区,计数区,代码区: 数据类型: 基本数据类型:整形,浮点型,布尔型 boolean 只能返回真假值,字符型: 引用数据类型:类,数组: 基本数据类型-->直接存放到栈区 ...

  3. HTML面试题

    1.你做的页面在哪些流览器测试过?这些浏览器的内核分别是什么? 所谓的“浏览器内核”无非指的是一个浏览器最核心的部分-“Rendering Engine”,直译叫做“渲染引擎”,我们也常称为“排版引擎 ...

  4. list与Set、Map区别

    1.List,Set都是继承自Collection接口,Map则不是 2.List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入 ...

  5. Vulkan Tutorial 12 Fixed functions

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 早起的图形API在图形渲染管线的许多阶段提供了默认的状态.在Vulkan中,从vie ...

  6. 华为A199:近期不会再买华为的手机了

    为了支持国货,也省点钱,买了个华为A199: 缺点: 没有google play market很复杂的刷机后才能装Gmail   不过也有亮点: 自带录音功能,老htc通过软件也只能录单方向的哦关机闹 ...

  7. ci框架学习告一段落,总结一下

    从网上弄了一张框架学习思维导图,从图中就可以看出ci用了设计模式中的MVC架构,使得用起来很简单方便 用了大概两个星期开发了一个<文章管理系统>觉得开发过程中学到了很多,挺不错的,而且在学 ...

  8. 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态序列

    隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态 ...

  9. scrapy设置"请求池"

    scrapy设置"请求池" 引言 相信大家有时候爬虫发出请求的时候会被ban,返回的是403错误,这个就是请求头的问题,其实在python发出请求时,使用的是默认的自己的请求头,网 ...

  10. 关于EasyUI中的Tree

    2017年6月21日,天气阴.心情比较沉重. 近期由于毕设的事情,三周不写代码了.这周测试提交了一些BUG,于是开始着手处理,还真的是熟能生巧,三周的功夫就感觉有点生疏.其中有一个BUG就是角色对应的 ...