首页 > 代码库 > 第二十章、分离应用程序逻辑并处理事件

第二十章、分离应用程序逻辑并处理事件

  理解委托

  委托是对方法的引用。(之所以称为委托,是因为一旦被调用,就将具体的处理“委托”给引用的方法)

  委托对象引用了方法,和将int赋值给int变量一样,是将方法引用赋给委托对象。

  Processor p = new Processor ();

  delegate...performCalculationDelegate...;

  performCalculationDelegate = p.performCalculation;//将方法引用赋给委托对象

  将方法引用赋给委托时,并不是马上就运行方法。方法名之后没有圆括号,也不指定任何参数。这纯粹就是一个赋值语句。

  将对Processor 对象的performCalculation方法的引用存储到委托中之后,应用程序就可通过委托来调用方法了,如下:

  performCalculationDelegate ();  //通过委托来调用方法

  另外,委托可一次引用多个方法(把它想象成方法引用集合)。一旦调用委托,所有方法都会运行。

  尚未引用有效方法的委托是不能调用的。

  谓词其实就是委托。只不过它恰好返回Boolean值而已。

  声明委托

  delegate void stopMachineryDelegate();

  注意一下几点:

  1、声明委托要使用delegate关键字。

  2、委托定义了它所引用的方法的“形式”。要指定返回类型(本例是void)、委托名称(stopMachineryDelegate)以及任何参数(本例无参数);

  定义好委托之后,就可创建它的实例,并用+=操作符让该实例引用匹配的方法。

  class Controller

  {

  delegate void stopMachineryDelegate(); //声明委托类型

  private stopMachineryDelegate stopMachinery; //创建委托实例

  ......

  public Controller()

  {

  this. stopMachinery += folder.StopFolding;

  }

  ........

  }

  上述语法只是将方法加到委托中;此时并没有实际调用方法。注意,只需指定方法名,不要包含任何圆括号或者参数。

  可安全地将+=操作符用于未初始化的委托。该委托将自动初始化。还可以使用new关键字显示初始化委托。让它引用一个特定的方法。

  this.StopMachinery = new stopMachineryDelegate(folder.StopFolding);

  可通过调用委托来调用它引用的方法,如下:

  public void ShutDown()

  {

  this. stopMachinery ();  //通过调用委托来调用它引用的方法

  }

  委托的主要优势在于它能引用多个方法;使用+=操作符把这些方法添加到委托中即可。就像这样:

  public Controller()

  {

  this. stopMachinery += folder.StopFolding;

  this. stopMachinery += welder.FinishWelding;

  this. stopMachinery += painter.PaintOff;

  }

  在Controller类的Shutdown方法中调用this. stopMachinery (),将自动依次调用上述每一个方法。

  使用-=复合赋值操作符,则可从委托中移除一个方法。

  如果方法与委托签名不匹配,假设StopFolding方法的签名实际是void StopFolding(int shutDownTime);

  1、创建方法适配器

  void FinishFolding()

  {

  folder. StopFolding(0);

  }

  2、Lambda表达式

  this.stopMachinery +=(() => folder. StopFolding(0));

  .NET Framework提供类事件。可定义并捕捉特定的事件,并在发生特定事件时调用委托来处理事件。

  声明事件

  事件在准备作为事件来源的类中声明。事件来源类监视其环境,在发生某件事情时引发事件。事件维护着方法列表,引发事件将调用这些方法。有时将这些方法称为订阅者。

  声明事件的方式与字段很相似。但由于事件随同委托使用,所有事件的类型必须是委托,而且必须在声明前附加event前缀。用以下语法声明事件:

  event delegateTypeName eventName //delegateTypeName是委托类型名称 eventName是事件名称

  如下:定义MachineOverheating事件,该事件将调用StopMachineryDelegate

  class TemperatureMonitor{

  public delegate void StopMachineryDelegate();

  public event StopMachineryDelegate MachineOverheating; //声明事件

  ..........

  }

  另外,要把方法添加到事件中——这个过程称为订阅事件或者向事件登记——而不是添加到事件基于的委托。

  订阅事件

  类似于委托,事件也用+=操作符进入就绪状态。我们使用+=操作符订阅事件。例如:

  class TemperatureMonitor{

  public delegate void StopMachineryDelegate();

  public event StopMachineryDelegate MachineOverheating; //声明事件

  ..........

  }

  .......

  TemperatureMonitor tempMonitor = new TemperatureMonitor();

  ......

  tempMonitor.MachineOverheating += () => {folder. StopFolding(0)};

  tempMonitor.MachineOverheating += welder.FinishWelding;

  tempMonitor.MachineOverheating += painter.PaintOff;

  tempMonitor.MachineOverheating 事件发生时,会调用所有订阅该事件的方法。

  取消订阅事件

  +=操作符用于订阅事件;对应地,-=操作符用于取消订阅。-=操作符将一个方法从事件的内部方法集合中移除。这个行动通常称为取消订阅事件或者从事件注销。

  引发事件

  和委托相似,可以把事件当作方法来调用,从而引发该事件。引发事件后,订阅了该事件的方法会依次调用。

  class TemperatureMonitor{

  public delegate void StopMachineryDelegate();

  public event StopMachineryDelegate MachineOverheating; //声明事件

  ..........

  private void Notify()

  {

  if(this.MachineryOverheating !=null)

  {

  this.MachineryOverheating(); //引发事件

  }

  }

  }

第二十章、分离应用程序逻辑并处理事件