一、事件的本质
      
举个例子你是个取向正常的青年男性,有个身材火辣,年轻貌美,腿长肤白的美女,冲你一笑,给你讲了一个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. 用pickle模块实现“增删改查”的简易功能

    pickle的作用: 1:pickle.dump(dict,file)把字典转为二进制存入文件. 2:pickle.load(file)把文件二进制内容转为字典 import pickle # 增 d ...

  2. Eclipse导入项目常见问题----乱码问题03

    有时打开导入的项目文件时,会出现如下图情况: 解决方法 如下图步骤所示: 此时,我们可以看到文件正常了 jdk版本问题(有个红色感叹号)01:http://blog.csdn.net/baidu_37 ...

  3. Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'URIType' of bean class [com.alibaba.citrus.service.uribroker.uri.GenericURIBroker]

    linux中的JDK为JDK8,tomcat为tomcat8 加入dubbo.war包 启动报错! Caused by: org.springframework.beans.factory.BeanC ...

  4. javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)

    javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...

  5. axis调用webservice的简单方法

    package com.service; import org.apache.axis.client.Call; import org.apache.axis.client.Service; publ ...

  6. 解决ionic2各种坑文章收集

    小白最近打算用ionic2做一个APP,无奈没有大神指点,一路坎坷遇到数不清的坑(主要是墙的问题).这里整理一些大神的帖子链接,用以指路. 新建/打包: Ionic2+Angular2创建项目打包An ...

  7. gradle 使用总结

    什么是gradle 书面化解释: Gradle可以自动化地进行软件构建.测试.发布.部署.软件打包,同时也可以完成项目相关功能如:生成静态网站.生成文档等. Gradle是一种依赖管理工具. 它和ma ...

  8. jersery+jetty嵌入式restful的框架开发

    随着微服务的流程,越来越多的后台服务采用了restful api风格的开放API,jersery+jetty嵌入式变成了一个很好的选择, 我自己写了一个简单的框架,https://github.com ...

  9. head first python helloword

    如何使用python 打出hello word 在python shell 键入print 'hello word'( python 2) or  print ("hello word&qu ...

  10. oracle备份、还原

    ----第一步:设置空表导出 ----由于Oracle 11G在用EXPORT导出时,空表不能导出.解决方法如下:(11G中有个新特性,当表无数据时,不分配segment,以节省空间) select ...