ASP.NET本质论
上QQ阅读APP看书,第一时间看更新

2.2.1 处理管道

所谓的处理管道,就是处理复杂问题的时候,将处理的过程分解为多个处理步骤,我们将这种经过多个步骤的处理方式称为处理管道。在.NET中,借助于事件的强大威力,我们可以通过处理管道将复杂的处理步骤封装起来,通过事件将处理过程的多个步骤暴露给程序员,以便于程序员对管理管道进行扩展。图2-1概述了HttpApplication处理管道的工作过程。

图2-1 HttpApplication 处理管道

对于一个管道来说,它往往要暴露出大量的事件,通过这些事件,提供程序员的扩展机制。

但是,对于一个有着众多事件的类来说,定义大量的事件意味着创建对象的时候需要付出创建事件的成本,因为在.NET中,所谓的事件就是一个受限制的委托成员,定义多个事件,意味着在创建的对象中将会需要更多的存储空间。针对这个问题,在System.ComponentModel.Component类中,提供了处理多个事件的基础:Events属性,它的类型为System.ComponentModel.EventHandlerList,这是一个线性的字典,当需要事件的时候,就通过key将事件保存到集合中,没有对应的事件,就不会付出创建事件的成本,这样,通过EventHandlerList可以在一个集合中管理多个事件对象,节省了事件对象占用的空间,它的主要成员如表 2-3所示。

表2-3 EventHandlerList的成员定义及说明

在使用的时候,首先从Component派生一个类,这个类将继承Component的Events集合属性。对于这个派生类所需要定义的每一个事件,在类中定义一个对应的作为key的对象,以后,通过这个key对象来访问由Events集合管理的事件。

程序员也可以自己在类中定义一个类似的字典来完成这个任务,并不一定要从Component类中的派生。

代码清单2-1通过实例演示了如何在类中定义多个事件,并创建一个处理管道。

代码清单2-1 在类中定义多个事件,并创建一个处理管道

public class ProcessPipeline: System.ComponentModel.Component
{
    #region
    private static readonly object startEvent = new object();
    private static readonly object preProcessEvent = new object();
    private static readonly object postProcessEvent = new object();
    private static readonly object endEvent = new object();
    #endregion
    #region
    public event EventHandler StartProcess
    {
        add { this.Events.AddHandler(startEvent, value); }
        remove { this.Events.RemoveHandler(startEvent, value); }
    }
    public event EventHandler PreProcess
    {
        add { this.Events.AddHandler(preProcessEvent, value); }
        remove { this.Events.RemoveHandler(preProcessEvent, value); }
    }
    public event EventHandler PostProcess
    {
        add { this.Events.AddHandler(postProcessEvent, value); }
        remove { this.Events.RemoveHandler(postProcessEvent, value); }
    }
    public event EventHandler EndProcess
    {
        add { this.Events.AddHandler(endEvent, value); }
        remove { this.Events.RemoveHandler(endEvent, value); }
    }
    #endregion
    #region
    protected void OnStartProcess(EventArgs e)
    {
        if (this.Events[startEvent] != null)
        {
            (this.Events[startEvent]as EventHandler)(this, e);
        }
    }
    protected void OnPreProcess(EventArgs e)
    {
        if (this.Events[preProcessEvent] != null)
        {
            (this.Events[preProcessEvent]as EventHandler)(this, e);
        }
    }
    protected void OnPostProcess(EventArgs e)
    {
        if (this.Events[postProcessEvent] != null)
        {
            (this.Events[postProcessEvent]as EventHandler)(this, e);
        }
    }
    protected void OnEndProcess(EventArgs e)
    {
        if (this.Events[endEvent] != null)
        {
            (this.Events[endEvent]as EventHandler)(this, e);
        }
    }
    #endregion
    //
    public void Process()
    {
        Console.WriteLine(" 开始处理");
        this.OnStartProcess(EventArgs.Empty);
        Console.WriteLine(" 准备处理");
        this.OnPreProcess(EventArgs.Empty);
        Console.WriteLine(" 正在处理中");
        Console.WriteLine(" 处理完成");
        this.OnPostProcess(EventArgs.Empty);
        Console.WriteLine(" 结束处理");
        this.OnEndProcess(EventArgs.Empty);
    }
}

在ProcessPipeline类中,定义了4个事件,首先需要注意的是在类中并没有定义4个实际的委托成员来对应事件,通过从Component 派生,实际上从基类继承了一个EventHandlerList类型的成员,通过将事件以属性的形式来定义,并映射到EventHandlerList中,不管在类中定义了多少个事件,在创建的对象实例中只需要这样一个EventHandlerList的对象来保存事件响应的委托对象。

其次,在Process方法中,模拟了处理的过程,在处理的过程中,通过调用触发事件的On开头的方法,以事件的形式将处理的步骤暴露给程序员。

使用这个类的时候,对于程序员关心的处理事件,可以通过注册事件处理方法到相应的事件上,在ProcessPipeline进行处理的过程中,相应的事件处理方法就会被调用。

下面的例子中,分别注册了5个顺序发生的事件:

class Program
{
    static void Main(string[]args)
    {
        ProcessPipeline process = new ProcessPipeline();
        process.StartProcess
             += new EventHandler(process_StartProcess);
        process.PreProcess
             += new EventHandler(process_PreProcess);
        process.PostProcess
             += new EventHandler(process_PostProcess);
        process.EndProcess
             += new EventHandler(process_EndProcess);
        process.Process();
    }
    static void process_StartProcess(object sender, EventArgs e)
    {
        Console.WriteLine(" 开始处理的事件处理...");
  }
  static void process_PreProcess(object sender, EventArgs e)
      {
         Console.WriteLine(" 处理前的事件处理...");
      }
  static void process_PostProcess(object sender, EventArgs e)
      {
         Console.WriteLine(" 处理后的事件处理...");
      }
      static void process_EndProcess(object sender, EventArgs e)
      {
          Console.WriteLine(" 处理完成的事件处理...");
      }
  }