事件提供了一种标准的机制来通知监听者。.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#代码:用事件模式实现通知的更多相关文章

  1. OneAlert 入门(四)——事件分派和通知必达

    OneAlert 是国内首个 SaaS 模式的云告警平台,集成国内外主流监控/支撑系统,实现一个平台上集中处理所有 IT 事件,提升 IT 可靠性.有了 OneAlert,你可以更快更合理地为事件划分 ...

  2. 【转载】详细解读C#中的 .NET 弱事件模式

    你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处理中展 ...

  3. C#中的 .NET 弱事件模式

    引言 你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处 ...

  4. 在WPF中应用弱事件模式

    http://www.cnblogs.com/rickiedu/archive/2007/03/15/676021.html 在wpf中应用弱事件模式        感谢VS 的Intellisens ...

  5. WPF程序中的弱事件模式

    在C#中,得益于强大的GC机制,使得我们开发程序变得非常简单,很多时候我们只需要管使用,而并不需要关心什么时候释放资源.但是,GC有的时并不是按照我们所期望的方式工作. 例如,我想实现一个在窗口的标题 ...

  6. Java小知识----POI事件模式读取Excel 2007

    一.知识背景 1.读取excel的方法选择问题 java中读excel中的时间,我们通常用POI去解析,在使用new HSSFWorkbook(NEW FileInputStream(excelFil ...

  7. 从B站的代码泄露事件中,我们能学到些什么?

    先声明一下,本文不聊ISSUE中的七七八八,也不聊代码是否写的好,更不聊是不是跟蔡徐坤有关之类的吃瓜内容.仅站在技术人的角度,从这次的代码泄露事件,聊聊在代码的安全管理上,通常都需要做哪些事来预防此类 ...

  8. 190行代码实现mvvm模式

    前言 网上讲 vue 原理,mvvm 模式的实现,数据双向绑定的文章一搜一大堆,不管写的谁好谁坏,都是写的自己的理解,我也发一篇文章记录自己的理解,如果对看官有帮助,那也是我莫大的荣幸,不过看完之后, ...

  9. C# 标准事件模式

    .NET框架为事件定义了一个标准模式,它的目的是保持框架和用户代码之间的一致性. 标准事件的模式核心是SystemEventArgs——预定义的没有成员的框架类(不同于静态Empty属性) Event ...

随机推荐

  1. 《用格式化(fprintf和fscanf函数)的方式读写文件》

    //用格式化(fprintf和fscanf函数)的方式读写文件 [用格式化的方式向文件中写入数据]#include<stdio.h>#include<stdlib.h> int ...

  2. 分析一个嵌入payload的恶意.lnk文件

    原文:https://isc.sans.edu/diary/Analyzis+of+a+Malicious+.lnk+File+with+an+Embedded+Payload/20763 We re ...

  3. maven3在eclipse3.4.2中创建java web项目

    学习maven时参考的一些的博客地址:http://www.cnblogs.com/fnng/archive/2011/12/16/2290587.htmlhttp://sarin.iteye.com ...

  4. 【Leetcode】 LRU Cache实现

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  5. 我的第一个unity3d Shader, 很简单,基本就是拷贝

    Shader "Castle/ColorMix" { Properties { // 基本贴图 _MainTex ("Texture Image", 2D) = ...

  6. iOS-微信支付平台

    微信支付1:去微信开放平台注册应用https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN&token=2c0f ...

  7. 在用的vim插件

    The-NERD-tree  https://github.com/vim-scripts/The-NERD-tree 在vim中也可以有目录树的,如果要打开当前文件夹下的其他文件的话也可以很方便的进 ...

  8. 扩展KVM镜像的虚拟磁盘大小

    当我们需要扩展模板镜像的虚拟磁盘大小时,比如原来的虚拟磁盘大小为20G,现在我们想将其扩展到30G,那么我们可以根据如下步骤来操作. 整个流程可以分为三个阶段: 1.扩展KVM镜像磁盘文件大小到30G ...

  9. htseq-count 的使用

    Given a file with aligned sequencing reads and a list of genomic features, a common task is to count ...

  10. FDR

    声明: 网上摘抄 False discovery rate (FDR) control is a statistical method used in multiple hypothesis test ...