您的位置:首页 > Web前端

《Effective C#》读书笔记——条目25:用事件模式实现通知<使用C#表达设计>

2013-01-18 23:59 1081 查看
  .NET中的事件其实就是一个观察者模式(Observer Pattern)的一个语法上的快捷实现(更多可以参考:使用委托和事件实现观察者模式)。事件是一种内建的委托,用来为事件处理函数提供类型安全的方法签名。事件就是对象将信息告知观察者的方式。

1.发布者定义事件

  我们来看一个例子,有一个日志类,将应用程序需要分发的信息发送个各个侦听者,这些侦听者可以是控制域、系统日志、数据库等等,首先定义一个在事件触发中负责传递消息的事件参数类:

public class LoggerEventArgs : EventArgs
{
public string message { get; private set; }
public int Priority { get; private set; }

public LoggerEventArgs(int p, string m)
{
this.Priority = p;
this.message = m;
}
}


然后是日志类本身:

public class Logger
{
static Logger()
{
theOnly = new Logger();
}

private Logger()
{
}

private static Logger theOnly = null;
public static Logger Singleton
{
get { return theOnly; }
}
//定义事件
public event EventHandler<LoggerEventArgs> Log;
//在这里增加消息和日志
public void AddMsg(int priority, string msg)
{
//这里引用临时变量是一个重要的安全措施,可预防多线程环境中的竞争条件
//若是没有引用的副本,客户代码可能会在if判断语句和事件处理函数之间移
//除事件处理函数,而复制引用之后即可避免这种情况
EventHandler<LoggerEventArgs> l = Log;
if (l != null)
l(this, new LoggerEventArgs(priority, msg));
}
}


在这里AddMsg()是触发事件的方法,LoggerEventArgs类中定义了事件的优先级和消息内容,委托则为事件处理函数定义了签名。在Logger类内部,事件自动Log定义了事件处理函数。编译器看到这个字段后会自动创建对应的Add和Remove操作符,编译器生成的代码和下面类似:

public class Logger
{
private EventHandler<LoggerEventArgs> log;

public event EventHandler<LoggerEventArgs> Log
{
add { log = log + value; }
remove { log = log - value; }
}
public void AddMsg(int priority, string msg)
{
EventHandler<LoggerEventArgs> l = log;
if (l != null)
l(this, new LoggerEventArgs(priority, msg));
}
}


或者我们可以直接查看IL代码:

View Code

public sealed class Logger
{
private static Dictionary<string, EventHandler<LoggerEventArgs>> Handlers = new Dictionary<string, EventHandler<LoggerEventArgs>>();

static public void AddLogger(string system, EventHandler<LoggerEventArgs> ev)
{
if (Handlers.ContainsKey(system))
Handlers[system] += ev;
else
Handlers.Add(system, ev);
}

static public void RemoveLogger(string system, EventHandler<LoggerEventArgs> ev)
{
Handlers[system] -= ev;
}

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);
}
}
}


小节


事件提供了一种标准的机制来通知侦听者。.NET的事件模式使用了事件语法来实现观察者模式。任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件。这些客户对象不需要在编译器就给出,事件也不必非有订阅者才能正常工作。在C#中使用事件可以降低发送者和可能的通知接收者之间的耦合。发送者完全可以独立于接收者进行开发。事件是实现广播类型行为的标准方式。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐