在基類中聲明可以從派生類引發的事件的標准方法。此模式廣泛應用於.Net Framework類庫中的Windows窗體類。
我們來看一個Button類的定義
public class Button : ButtonBase, IButtonControl { protected override void OnClick(EventArgs e); //override基類的事件觸發程序 }
我們通過ButtonBase最後找到基類Control
public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IArrangedElement, IBindableComponent, IComponent, IDisposable { public event EventHandler Click; //基類中定義事件 protected virtual void OnClick(EventArgs e);//protected封裝事件觸發程序,允許繼承類調用或重寫 }
在包含事件的基類中創建一個受保護的調用方法。通過調用或重寫方法,派生類便可以間接調用該事件。
我們來看一個例子:
namespace BaseClassEvents { //Special EventArgs class to hold info about Shapes. public class ShapeEventArgs:EventArgs { private double newArea; public ShapeEventArgs (double d) { newArea = d; } public double NewArea { get { return newArea; } } } //Declare a delegate public delegate void CustomEventHandler(object sender, ShapeEventArgs e); //Base class event publisher public abstract class Shape { protected double area; public double Area { get { return area; } set { area = value; } } //raise an event public event CustomEventHandler ShapeChanged; public abstract void Draw(); //event-invoking method protected virtual void OnShapeChanged(ShapeEventArgs e) { if(ShapeChanged !=null) { ShapeChanged(this, e); } } } public class Circle:Shape { private double radius; public Circle (double d) { radius = d; area = 3.14 * radius * radius; } public void Update(double d) { radius = d; area = 3.14 * radius * radius; OnShapeChanged(new ShapeEventArgs(area)); } protected override void OnShapeChanged(ShapeEventArgs e) { base.OnShapeChanged(e); } public override void Draw() { Console.WriteLine("Drawing a circle"); } } public class Rectangle:Shape { private double length; private double width; public Rectangle (double length,double width) { this.length = length; this.width = width; area = length * width; } public void Update(double length,double width) { this.length = length; this.width = width; area = length * width; OnShapeChanged(new ShapeEventArgs(area)); } protected override void OnShapeChanged(ShapeEventArgs e) { base.OnShapeChanged(e); } public override void Draw() { Console.WriteLine("Drawing a rectangle"); } } //Subscriber //Represents the surface on which the shapes are drawn //Subscibes to shape events so that it knows //when to redraw a shape public class ShapeContainer { List<Shape> _list; public ShapeContainer () { _list = new List<Shape>(); } public void AddShape(Shape s) { _list.Add(s); //Subscribe to the base class event. s.ShapeChanged += HandleShapeChanged; } private void HandleShapeChanged(object sender,ShapeEventArgs e) { Shape s = (Shape)sender; Console.WriteLine("Received event. Shape area is now {0}", e.NewArea); s.Draw(); } } class Program { static void Main(string[] args) { //Create the event publishers and subscriber Circle c1 = new Circle(54); Rectangle r1 = new Rectangle(12, 9); ShapeContainer sc = new ShapeContainer(); //Add the shapes to the container sc.AddShape(c1); sc.AddShape(r1); //Cause some events to be raised c1.Update(57); r1.Update(7, 7); Console.ReadKey(); } } }