一、事件的本质
      
举个例子你是个取向正常的青年男性,有个身材火辣,年轻貌美,腿长肤白的美女,冲你一笑,给你讲了一个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下sublime text3 安装px转rem插件

    本人使用的是os-x系统,即mac系统,每次使用单位rem用其他网页转换很不方便.自己捣腾了一下插件,现在共享给大家 第一步: 先下载插件: https://github.com/narrow-gat ...

  2. 在ie下,a标签包被img的时候,为什么有个蓝色的边线

    效果像下图这样 那是由于<img>在ie下有默认边框,只要清除边框就可以了,在style中定义 img{ border:none } 显示效果就变成下面这样了 完!

  3. 怎么一次性获取form所有的值?rerialize() 、 serializeArray()方法的使用

    from直接提交当然方便,但是有时候需要对数据进行处理再用ajax提交,挨个去获取值未免太麻烦,讲两个一次性获取所有值的方法. 方法1 $("form").serialize(); ...

  4. Mac下将ISO写入U盘镜像

    在Mac下面如果想做一个启动U盘,确实不如windows下那么方便,Windows下面有ultraiso+王涛,Mac下面测可以用下面的办法. 打开磁盘工具 插入U盘,并在磁盘工具里面找到U盘,把它卸 ...

  5. 【数据库】Mean web开发 04-MongoDB在Linux上的安装及遇到的问题

    简介 Mean是JavaScript的全栈开发框架.更多介绍 用MongoDB实现持久数据的存储是Mean Web全栈开发中的一部分. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非 ...

  6. HTML5 客户端存储数据的两种方式

    HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 之前,这些都是由 coo ...

  7. jsp中怎么调用java类中的方法

    在jsp页面中先要,引入java类 例如: <%@page import="javabean.DbConn"%><!-- 引入包中的"类" - ...

  8. 利用php做出简单的发布信息和回复功能

    题目要求 1.建一个pinglun的数据库,自己建表2.完成一个简单的发布信息回复功能3.布局可以随便,主要是功能要实现4.注意回复是可以回复每一条的评论5.评论回复功能类似于qq空间的发布信息和回复 ...

  9. html锚点 点击跳转到页面指定位置

    本来是在看阮大神写的ajax教程,突然发现点击目录文字会跳转到相对应的文本内容,于是乎激发了我的兴趣. 这个究竟怎么做的,刚开始看的时候一知半解,找度娘就是:"点击跳转到页面指定位置&quo ...

  10. CSS设置一行文字,超出部分自动隐藏

    .textone { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; line-height: 25px; max-h ...