事件提供了一种标准的机制来通知监听者。.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. 2013年9月份第2周51Aspx源码发布详情

    休闲农庄企业站源码  2013-9-13 [VS2008]功能介绍:  首页功能:关于我们 资讯中心 休闲娱乐 餐饮娱乐 环境展示 园林展示 交通指引 联系我们  后台功能:      基本信息:服务 ...

  2. ZOJ 1654 - Place the Robots (二分图最大匹配)

    题意:在一个m*n的地图上,有空地,草和墙,其中空地和草能穿透攻击光线,而墙不能.每个机器人能够上下左右攻击,问在地图上最多能放多少个不互相攻击的机器人. 这个题和HDU 1045 -  Fire N ...

  3. 一个有趣的IE内核检测网站

    http://se.360.cn/v5/iecoretest.html 该网站能有效检测您浏览器的内核,以及版本,操作系统. 找到这个网址,是因为最近解决WebBrowser自动调节IE版本功能时发现 ...

  4. 获得servletContext的路径的方法

    request.getSession().getServletContext().getRealPath("")或 System.getProperty("webapp. ...

  5. java generic type

    java generic type: 类型安全.类型参数化.不需要强制转换

  6. python3 nonlocal vs global

    考虑这样一个python程序: x = 12 def func(): x = 1 func() print(x) 输出为:x = 12 因为函数内部定义的x被认为只属于局部作用域,为了表明我么引用的是 ...

  7. linux下解决端口被占用的问题

    以端口9877为例,先查看是否有进程占用该端口 netstat -tln | grep 9877 然后查看占用该端口的进程的进程id lsof -i :9877 最后kill 命令结束该进程: kil ...

  8. 《view programming guide for iOS 》之可以使用动画效果的属性

    frame—Use this to animate position and size changes for the view.  ,框架,可以视图动态改变大小和位置 bounds—Use this ...

  9. 监听Android CTS测试项解决方案(一)

    前言: 首先这里需要详细叙述一下标题中"监听Android CTS测试项解决方案"的需求.这里的需求是指我们需要精确的监听到当前CTS测试正在测试的测试项. 因为我们知道CTS认证 ...

  10. yii2 数据验证

    控制器层 <?php namespace frontend\controllers; use Yii; use frontend\models\FormsModel; use yii\web\U ...