如何:實作介面事件 (C# 程式設計手冊)
介面可以宣告事件。 下列範例會示範如何在類別內實作介面事件, 其規則基本上與實作任何介面方法或屬性相同。
若要在類別內實作介面事件
在類別內宣告該事件,然後在適當的區域予以叫用。
namespace ImplementInterfaceEvents { public interface IDrawingObject { event EventHandler ShapeChanged; } public class MyEventArgs : EventArgs { // class members } public class Shape : IDrawingObject { public event EventHandler ShapeChanged; void ChangeShape() { // Do something here before the event… OnShapeChanged(new MyEventArgs(/*arguments*/)); // or do something here after the event. } protected virtual void OnShapeChanged(MyEventArgs e) { if(ShapeChanged != null) { ShapeChanged(this, e); } } } }
範例
下列範例會示範如何處理一個較不常見的狀況,也就是您的類別繼承自兩個或多個介面,而每一個介面都有一個同名的事件。 在這種情形下,您至少必須為其中一個事件提供明確的介面實作 (Implementation)。 當您為事件撰寫明確的介面實作時,也必須撰寫 add 和 remove 事件存取子 (Accessor)。 通常這些事件存取子是由編譯器 (Compiler) 所提供,但在這個情況下,編譯器無法提供這些事件存取子。
提供您自己的存取子後,您就可以指定這兩個事件會以類別內的相同事件還是不同事件來表示。 例如,如果根據介面的指定,事件應該在不同時間引發,您便可以讓每一個事件與類別內的各個實作產生關聯。 在下列範例中,訂閱者會藉由轉換 IShape 或 IDrawingObject 的圖案參考,以判斷將會接收到哪一個 OnDraw 事件。
namespace WrapTwoInterfaceEvents
{
using System;
public interface IDrawingObject
{
// Raise this event before drawing
// the object.
event EventHandler OnDraw;
}
public interface IShape
{
// Raise this event after drawing
// the shape.
event EventHandler OnDraw;
}
// Base class event publisher inherits two
// interfaces, each with an OnDraw event
public class Shape : IDrawingObject, IShape
{
// Create an event for each interface event
event EventHandler PreDrawEvent;
event EventHandler PostDrawEvent;
object objectLock = new Object();
// Explicit interface implementation required.
// Associate IDrawingObject's event with
// PreDrawEvent
event EventHandler IDrawingObject.OnDraw
{
add
{
lock (objectLock)
{
PreDrawEvent += value;
}
}
remove
{
lock (objectLock)
{
PreDrawEvent -= value;
}
}
}
// Explicit interface implementation required.
// Associate IShape's event with
// PostDrawEvent
event EventHandler IShape.OnDraw
{
add
{
lock (objectLock)
{
PostDrawEvent += value;
}
}
remove
{
lock (objectLock)
{
PostDrawEvent -= value;
}
}
}
// For the sake of simplicity this one method
// implements both interfaces.
public void Draw()
{
// Raise IDrawingObject's event before the object is drawn.
EventHandler handler = PreDrawEvent;
if (handler != null)
{
handler(this, new EventArgs());
}
Console.WriteLine("Drawing a shape.");
// RaiseIShape's event after the object is drawn.
handler = PostDrawEvent;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
public class Subscriber1
{
// References the shape object as an IDrawingObject
public Subscriber1(Shape shape)
{
IDrawingObject d = (IDrawingObject)shape;
d.OnDraw += new EventHandler(d_OnDraw);
}
void d_OnDraw(object sender, EventArgs e)
{
Console.WriteLine("Sub1 receives the IDrawingObject event.");
}
}
// References the shape object as an IShape
public class Subscriber2
{
public Subscriber2(Shape shape)
{
IShape d = (IShape)shape;
d.OnDraw += new EventHandler(d_OnDraw);
}
void d_OnDraw(object sender, EventArgs e)
{
Console.WriteLine("Sub2 receives the IShape event.");
}
}
public class Program
{
static void Main(string[] args)
{
Shape shape = new Shape();
Subscriber1 sub = new Subscriber1(shape);
Subscriber2 sub2 = new Subscriber2(shape);
shape.Draw();
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
/* Output:
Sub1 receives the IDrawingObject event.
Drawing a shape.
Sub2 receives the IShape event.
*/