C#代码:用事件模式实现通知
事件提供了一种标准的机制来通知监听者。.NET的事件模式使用了事件语法来实现观察者模式。任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件。这些客户对象不需要再编译期就给出。时间也不必非要有订阅者才能正常工作。在C#中使用事件可以降低发送者和可能的通知接受者之间的耦合。发送者可以完全独立于接收者进行开发。事件是实现广播类型行为信息的标准方式。
下面按照使用场景的不同,简单列举三种事件模式的实现方式:
. 公共代码部分
/// <summary>
复制代码
/// 日志参数类
/// </summary>
public class LoggerEventArgs : EventArgs
{
public string Message { get; private set; }
public int Priority { get; private set; }
public LoggerEventArgs(int p, string m)
{
Priority = p;
Message = m;
}
}
复制代码
. 最常用方式
/// <summary>
复制代码
/// 日志类(第一版):最常见的使用方法,适用于单一调用者情况。
/// </summary>
public class Logger
{
/// <summary>
/// 内部事件句柄
/// </summary>
public event EventHandler<LoggerEventArgs> Log;
/// <summary>
/// 内部日志单键实例
/// </summary>
private static Logger theOnly = null;
public static Logger Singleton
{
get { return theOnly; }
}
private Logger()
{ }
static Logger()
{
theOnly = new Logger();
}
/// <summary>
/// 添加日志信息
/// </summary>
/// <param name="priority"></param>
/// <param name="msg"></param>
public void AddMsg(int priority, string msg)
{
// 该临时变量可预防多线程环境中的竞争条件
EventHandler<LoggerEventArgs> l = Log;
// 执行事件方法
if (l != null)
{
l(this, new LoggerEventArgs(priority, msg));
}
}
}
复制代码
. 针对事件数量多的情况
/// <summary>
复制代码
/// 日志类(第二版):适用于包含事件数量非常多的情况,即添加了一个事件容器,避免因多事件导致的设计臃肿。
/// </summary>
public sealed class Logger
{
/// <summary>
/// 事件容器
/// </summary>
private static System.ComponentModel.EventHandlerList Handlers = new System.ComponentModel.EventHandlerList();
/// <summary>
/// 添加事件
/// </summary>
/// <param name="system"></param>
/// <param name="ev"></param>
public static void AddLogger(string system, EventHandler<LoggerEventArgs> ev)
{
Handlers.AddHandler(system, ev);
}
/// <summary>
/// 清除事件
/// </summary>
/// <param name="system"></param>
/// <param name="ev"></param>
public static void RemoveLogger(string system, EventHandler<LoggerEventArgs> ev)
{
Handlers.RemoveHandler(system, ev);
}
/// <summary>
/// 添加日志信息
/// </summary>
/// <param name="system"></param>
/// <param name="priority"></param>
/// <param name="msg"></param>
public static void AddMsg(string system, int priority, string msg)
{
if (!string.IsNullOrEmpty(system))
{
// 根据key获取相应的事件
EventHandler<LoggerEventArgs> l = Handlers[system] as EventHandler<LoggerEventArgs>;
// 事件参数
LoggerEventArgs args = new LoggerEventArgs(priority, msg);
if (l != null)
{
l(null, args);
}
// 若不存在,执行默认事件
l = Handlers[""] as EventHandler<LoggerEventArgs>;
if (l != null)
{
l(null, args);
}
}
}
}
复制代码
. 针对事件数量多的情况(泛型版本)
/// <summary>
复制代码
/// 日志类(第三版):适用于多事件情况的泛型版本。主要优势是降低了转型/转换的工作,但增加了一些用来映射事件的代码。
/// </summary>
public sealed class Logger
{
/// <summary>
/// 事件字典
/// </summary>
private static Dictionary<string, EventHandler<LoggerEventArgs>> Handlers = new Dictionary<string, EventHandler<LoggerEventArgs>>();
/// <summary>
/// 添加事件
/// </summary>
/// <param name="system"></param>
/// <param name="ev"></param>
static public void AddLogger(string system, EventHandler<LoggerEventArgs> ev)
{
if (Handlers.ContainsKey(system))
{
Handlers[system] += ev;
}
else
{
Handlers.Add(system, ev);
}
}
/// <summary>
/// 清除事件
/// </summary>
/// <param name="system"></param>
/// <param name="ev"></param>
static public void RemoveLogger(string system, EventHandler<LoggerEventArgs> ev)
{
Handlers[system] -= ev;
}
/// <summary>
/// 添加日志信息
/// </summary>
/// <param name="system"></param>
/// <param name="priority"></param>
/// <param name="msg"></param>
static public void AddMsg(string system, int priority, string msg)
{
if (string.IsNullOrEmpty(system))
{
// 从字典中获取事件
EventHandler<LoggerEventArgs> l = null;
Handlers.TryGetValue(system, out l);
// 事件参数
LoggerEventArgs args = new LoggerEventArgs(priority, msg);
// 执行事件
if (l != null)
{
l(null, args);
}
// 若不存在,则尝试执行默认事件
l = Handlers[""] as EventHandler<LoggerEventArgs>;
if (l != null)
{
l(null, args);
}
}
}
}
复制代码
至于选择哪种方式来实现,就要看具体的应用场景了;此外,大多数时候我们都会使用匿名委托来声明回调函数,或事件委托,所以会导致代码的运行时态有一些小波折,尤其在读别人的代码的时候,这样的情况很普遍,会不会有更好的办法来让这种回调和委托比较容易跟踪?这个还在思考中……
C#代码:用事件模式实现通知的更多相关文章
- OneAlert 入门(四)——事件分派和通知必达
OneAlert 是国内首个 SaaS 模式的云告警平台,集成国内外主流监控/支撑系统,实现一个平台上集中处理所有 IT 事件,提升 IT 可靠性.有了 OneAlert,你可以更快更合理地为事件划分 ...
- 【转载】详细解读C#中的 .NET 弱事件模式
你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处理中展 ...
- C#中的 .NET 弱事件模式
引言 你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处 ...
- 在WPF中应用弱事件模式
http://www.cnblogs.com/rickiedu/archive/2007/03/15/676021.html 在wpf中应用弱事件模式 感谢VS 的Intellisens ...
- WPF程序中的弱事件模式
在C#中,得益于强大的GC机制,使得我们开发程序变得非常简单,很多时候我们只需要管使用,而并不需要关心什么时候释放资源.但是,GC有的时并不是按照我们所期望的方式工作. 例如,我想实现一个在窗口的标题 ...
- Java小知识----POI事件模式读取Excel 2007
一.知识背景 1.读取excel的方法选择问题 java中读excel中的时间,我们通常用POI去解析,在使用new HSSFWorkbook(NEW FileInputStream(excelFil ...
- 从B站的代码泄露事件中,我们能学到些什么?
先声明一下,本文不聊ISSUE中的七七八八,也不聊代码是否写的好,更不聊是不是跟蔡徐坤有关之类的吃瓜内容.仅站在技术人的角度,从这次的代码泄露事件,聊聊在代码的安全管理上,通常都需要做哪些事来预防此类 ...
- 190行代码实现mvvm模式
前言 网上讲 vue 原理,mvvm 模式的实现,数据双向绑定的文章一搜一大堆,不管写的谁好谁坏,都是写的自己的理解,我也发一篇文章记录自己的理解,如果对看官有帮助,那也是我莫大的荣幸,不过看完之后, ...
- C# 标准事件模式
.NET框架为事件定义了一个标准模式,它的目的是保持框架和用户代码之间的一致性. 标准事件的模式核心是SystemEventArgs——预定义的没有成员的框架类(不同于静态Empty属性) Event ...
随机推荐
- java应用程序和虚拟机实例之间的关系
每一个java程序都会产生一个java虚拟机的实例.并不是说一个物理机上,运行多个java应用程序就只有一个java虚拟机实例,多少个java应用程序就有多少个java虚拟机实例.
- MySQL中like的使用方法
Like的运用场合主要在模糊查询的时候,一般以查询字符串居多,这里据一些例子来说他的一般用法: <1>查询name字段中包含有“明”字的:例 select * from table1 wh ...
- (转)tomcat与地址栏图标之研究(多浏览器)
原文:http://hi.baidu.com/hebo_thu/item/fc8c81bb164f5cee4fc7fd90 tomcat与地址栏图标之研究(多浏览器) 最近在做一个java网络应用程序 ...
- 2016 - 1 -17 GCD学习总结
一:GCD中的两个核心概念,队列与任务: 1.任务:执行什么操作.(代码块 block) 任务执行的类型分为以下两种: 1.1同步执行任务:在当前线程执行任务.不会开辟新的线程. 1.2异步执行任务: ...
- C118 免按开机自动加载固件
最近无事,研究了按按钮开机的功能:功能的起初是参考了别人的系统是怎么做免开机加载固件的. 一.原理: 1.c118 原生loader部分代码是没有源代码的,它上电只需要按开机键然后系统就会起来. 2. ...
- 爬虫学习----pattern
1.match match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]): 这个方法将从string的pos下标处起尝试匹 ...
- VM设置BIOS延长时间
更改文件中的 bios.bootDelay = "XXXX"
- 【转】C 宏
http://www.cs.yale.edu/homes/aspnes/pinewiki/C%282f%29Macros.html See KernighanRitchie Appendix A12. ...
- Use XML in Windows Phone 8.0
I have an XML file stored in DataModel folder, the structure is shown as below: <?xml version=&qu ...
- C++学习笔记35:函数模板
函数模板 函数模板的目的 设计通用的函数,以适应广泛的数据型式 函数模板的定义格式 template<模板型式参数列表>返回值型式 函数名称(参数列表): 原型:template<c ...