c#用事件模式实现通知
2011-09-01 12:26
525 查看
改进C#代码之25:用事件模式实现通知
事件提供了一种标准的机制来通知监听者。.NET的事件模式使用了事件语法来实现观察者模式。任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件。这些客户对象不需要再编译期就给出。时间也不必非要有订阅者才能正常工作。在C#中使用事件可以降低发送者和可能的通知接受者之间的耦合。发送者可以完全独立于接收者进行开发。事件是实现广播类型行为信息的标准方式。下面按照使用场景的不同,简单列举三种事件模式的实现方式:
0. 公共代码部分
1 /// <summary>
2 /// 日志参数类
3 /// </summary>
4 public class LoggerEventArgs : EventArgs
5 {
6 public string Message { get; private set; }
7 public int Priority { get; private set; }
8
9 public LoggerEventArgs(int p, string m)
{
Priority = p;
Message = m;
}
}
1. 最常用方式
1 /// <summary>
2 /// 日志类(第一版):最常见的使用方法,适用于单一调用者情况。
3 /// </summary>
4 public class Logger
5 {
6 /// <summary>
7 /// 内部事件句柄
8 /// </summary>
9 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));
}
}
}
2. 针对事件数量多的情况
1 /// <summary>
2 /// 日志类(第二版):适用于包含事件数量非常多的情况,即添加了一个事件容器,避免因多事件导致的设计臃肿。
3 /// </summary>
4 public sealed class Logger
5 {
6 /// <summary>
7 /// 事件容器
8 /// </summary>
9 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);
}
}
}
}
3. 针对事件数量多的情况(泛型版本)
1 /// <summary>
2 /// 日志类(第三版):适用于多事件情况的泛型版本。主要优势是降低了转型/转换的工作,但增加了一些用来映射事件的代码。
3 /// </summary>
4 public sealed class Logger
5 {
6 /// <summary>
7 /// 事件字典
8 /// </summary>
9 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#代码:用事件模式实现通知
- C#用事件模式实现通知 from: http://www.cnblogs.com/guilin_gavin/archive/2011/08/18/2144397.html
- 《Effective C#》读书笔记——条目25:用事件模式实现通知<使用C#表达设计>
- 改进C#代码之25:用事件模式实现通知
- WCF中使用观察者模式实现事件通知
- WCF中使用观察者模式实现事件通知
- C# 利用事件实现观察者模式
- C#中使用委托和事件实现观察者模式(observer pattern)
- C#中使用委托和事件实现观察者模式(observer pattern)
- 实现一个简单的事件订阅通知机制(Observer模式实现)
- 用C#中的委托和事件简单实现观察者模式
- WPF中MVVM模式下的按钮事件实现和依赖项通知
- 事件模式实现通知
- C#的委托事件在winform窗体中实现传值备忘
- lua实现c#事件机制
- 设计模式学习----观察者模式(事件监听实现)
- 用java语言实现事件委托模式
- 由c#事件监听、回调函数引发观察者模式
- 利用C#实现标准的Dispose模式
- 在Unity3D中基于订阅者模式怎样实现事件机制