방법: 클래스에 이벤트 구현
다음 절차에서는 클래스의 이벤트를 구현하는 방법을 설명합니다. 첫 번째 절차에서는 연결된 데이터가 없는 이벤트를 구현합니다. 여기서는 이벤트 데이터와 대리자 처리기의 System.EventArgs 및 System.EventHandler 클래스를 사용합니다. 두 번째 절차에서는 사용자 지정 데이터가 있는 이벤트를 구현합니다. 여기서는 이벤트 데이터와 이벤트 대리자 처리기의 사용자 지정 클래스를 정의합니다.
참고
이 항목에서는 클래스에서 이벤트를 선언하고 발생시키는 방법에 대해서만 설명하고해당 이벤트를 사용하는 이벤트 처리기를 정의하는 방법에 대해서는 설명하지 않습니다.이벤트를 사용하는 방법에 대한 자세한 내용은 이벤트 사용 및 방법: 이벤트 발생 및 사용을 참조하십시오.
이벤트를 발생시키고 처리하는 방법을 보여 주는 전체 예제는 방법: 이벤트 발생 및 사용을 참조하십시오.
이벤트 관련 데이터 없이 이벤트를 구현하려면
클래스에서 공용 이벤트 멤버를 정의합니다. 이벤트 멤버의 형식을 System.EventHandler 대리자로 설정합니다.
Public Class Countdown ' ... Public Event CountdownCompleted As EventHandler End Class
public class Countdown { // ... public event EventHandler CountdownCompleted; }
이벤트를 발생시키는 보호된 메서드를 클래스에 제공합니다. 메서드 이름을 OnEventName으로 지정합니다. 메서드 내에서 이벤트를 발생시킵니다. C# 코드에서는 이벤트를 발생시키기 전에 이벤트가 null인지 여부를 확인해야 합니다. 이렇게 하면 이벤트가 발생했지만 해당 이벤트에 연결된 이벤트 처리기가 없을 때 throw되는 NullReferenceException을 처리하지 않아도 됩니다. 이 경우에는 CountDown 클래스가 이벤트를 발생시키기만 하고 해당 이벤트에 대한 처리기를 제공하지 않으므로 이 검사가 필요합니다.
Public Class Countdown ' ... Public Event CountdownCompleted As EventHandler Protected Overridable Sub OnCountdownCompleted(e As EventArgs) RaiseEvent CountdownCompleted(Me, e) End Sub End Class
public class Countdown { public event EventHandler CountdownCompleted; protected virtual void OnCountdownCompleted(EventArgs e) { if (CountdownCompleted != null) CountdownCompleted(this, e); } }
클래스에서 이벤트를 발생시킬 시기를 결정합니다. OnEventName을 호출하여 이벤트를 발생시킵니다.
Public Class Countdown Dim internalCounter As Integer = 0 ' ... Public Event CountdownCompleted As EventHandler Protected Overridable Sub OnCountdownCompleted(e As EventArgs) RaiseEvent CountdownCompleted(Me, e) End Sub Public Sub Decrement() internalCounter -= 1 If internalCounter = 0 OnCountdownCompleted(New EventArgs()) End If End Sub End Class
public class Countdown { int internalCounter = 0; // ... public event EventHandler CountdownCompleted; protected virtual void OnCountdownCompleted(EventArgs e) { if (CountdownCompleted != null) CountdownCompleted(this, e); } public void Decrement() { internalCounter--; if (internalCounter == 0) OnCountdownCompleted(new EventArgs()); } }
이벤트 관련 데이터가 있는 이벤트를 구현하려면
이벤트에 대한 데이터를 제공하는 클래스를 정의합니다. 클래스 이름을 EventNameArgs로 지정하고 System.EventArgs에서 클래스를 파생한 다음 이벤트 관련 멤버를 추가합니다.
Public Class AlarmEventArgs : Inherits EventArgs Private nRings As Integer = 0 Private pressed As Boolean = False Private text As String = "The alarm is ringing!" ' Constructor. Public Sub New(ByVal snoozePressed As Boolean, ByVal nRings As Integer) Me.pressed = snoozePressed Me.nRings = nRings End Sub ' Properties. Public Property AlarmText() As String Get Return Me.text End Get Set Me.text = value End Set End Property Public ReadOnly Property NumRings() As Integer Get Return Me.nRings End Get End Property Public ReadOnly Property SnoozePressed() As Boolean Get Return Me.pressed End Get End Property End Class
public class AlarmEventArgs : EventArgs { private readonly int nRings = 0; private readonly bool pressed = false; private string text = "The alarm is ringing!"; // Constructor. public AlarmEventArgs(bool snoozePressed, int nRings) { this.pressed = snoozePressed; this.nRings = nRings; } // Properties. public string AlarmText { get { return text; } set { this.text = value; } } public int NumRings { get { return nRings; } } public bool SnoozePressed { get { return pressed; } } }
이벤트의 대리자를 선언합니다. 대리자 이름을 EventNameEventHandler로 지정합니다.
Public Delegate Sub AlarmEventHandler(sender As Object, e As AlarmEventArgs)
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
클래스에서 EventName이라는 공용 이벤트 멤버를 정의합니다. 이벤트 멤버의 형식을 이벤트 대리자 형식으로 설정합니다.
Public Class AlarmClock ' ... Public Event Alarm As AlarmEventHandler End Class
public class AlarmClock { // ... public event AlarmEventHandler Alarm; }
이벤트를 발생시키는 보호된 메서드를 클래스에서 정의합니다. 메서드 이름을 OnEventName으로 지정합니다. 메서드 내에서 이벤트를 발생시킵니다. C# 코드에서는 이벤트를 발생시키기 전에 이벤트가 null인지 여부를 확인해야 합니다. 이렇게 하면 이벤트가 발생했지만 해당 이벤트에 연결된 이벤트 처리기가 없을 때 throw되는 NullReferenceException을 처리하지 않아도 됩니다. 이 경우에는 CountDown 클래스가 이벤트를 발생시키기만 하고 해당 이벤트에 대한 처리기를 제공하지 않으므로 이 검사가 필요합니다.
Public Class AlarmClock ' ... Public Event Alarm As AlarmEventHandler Protected Overridable Sub OnAlarm(e As AlarmEventArgs) RaiseEvent Alarm(Me, e) End Sub End Class
public class AlarmClock { // ... public event AlarmEventHandler Alarm; protected virtual void OnAlarm(AlarmEventArgs e) { if (Alarm != null) Alarm(this, e); } }
클래스에서 이벤트를 발생시킬 시기를 결정합니다. OnEventName을 호출하여 이벤트를 발생시키고 EventNameEventArgs를 사용하여 이벤트 관련 데이터를 전달합니다.
Public Class AlarmClock Public Sub Start ' ... System.Threading.Thread.Sleep(300) Dim e As AlarmEventArgs = New AlarmEventArgs(False, 0) OnAlarm(e) End Sub Public Event Alarm As AlarmEventHandler Protected Overridable Sub OnAlarm(e As AlarmEventArgs) RaiseEvent Alarm(Me, e) End Sub End Class
public class AlarmClock { public void Start() { // ... System.Threading.Thread.Sleep(300); AlarmEventArgs e = new AlarmEventArgs(false, 0); OnAlarm(e); } public event AlarmEventHandler Alarm; protected virtual void OnAlarm(AlarmEventArgs e) { if (Alarm != null) Alarm(this, e); } }
예제
다음 예제에서는 이벤트를 사용하여 사용 가능한 디스크 공간이 구성 파일에 정의된 비율보다 적어질 때마다 경고를 발생시키는 DiskSpaceMonitor 클래스를 정의하고, 이벤트 처리기에 사용 가능한 디스크 공간에 대한 사용자 지정 데이터를 제공하는 DiskSpaceWarningEventArgs 클래스도 정의합니다.
Imports System.Collections.Specialized
Imports System.Configuration
Imports System.IO
Public Class DiskSpaceWarningEventArgs : Inherits EventArgs
Dim currentFreeSpace As Long
Dim currentTotalSpace As Long
Dim driveName As String
Public Sub New(name As String, freeSpace As Long, totalSpace As Long)
Me.driveName = name
Me.currentFreeSpace = freeSpace
Me.currentTotalSpace = totalSpace
End Sub
Public ReadOnly Property Name As String
Get
Return Me.driveName
End Get
End Property
Public ReadOnly Property FreeSpace As Long
Get
Return Me.currentFreeSpace
End Get
End Property
Public ReadOnly Property TotalSpace As Long
Get
Return Me.currentTotalSpace
End Get
End Property
End Class
Public Delegate Sub DiskSpaceWarningEventHandler(sender As Object, _
e As DiskSpaceWarningEventArgs)
Public Class DiskSpaceMonitor
Public Event DiskSpaceWarning As DiskSpaceWarningEventHandler
Private threshhold As Decimal
Public Sub New()
' Retrieve threshhold to fire event from configuration file.
Try
Dim settings As NameValueCollection = ConfigurationManager.AppSettings
Me.threshhold = CDec(settings.Item("Threshhold"))
' If there is no configuration file, provide a default value.
Catch e As ConfigurationErrorsException
Me.threshhold = 10d
Catch e As InvalidCastException
Me.threshhold = 10d
End Try
End Sub
Public Sub CheckFreeSpace
' Get drives present on system.
Dim drives() As DriveInfo = DriveInfo.GetDrives()
For Each drive As DriveInfo In drives
If drive.IsReady Then
If drive.TotalFreeSpace/drive.TotalSize <= Me.threshhold Then
OnDiskSpaceWarning(New DiskSpaceWarningEventArgs(drive.Name, _
drive.TotalFreeSpace, drive.TotalSize))
End If
End If
Next
End Sub
Protected Sub OnDiskSpaceWarning(e As DiskSpaceWarningEventArgs)
RaiseEvent DiskSpaceWarning(me, e)
End Sub
End Class
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
public class DiskSpaceWarningEventArgs : EventArgs
{
private long currentFreeSpace;
private long currentTotalSpace;
private string driveName;
public DiskSpaceWarningEventArgs(string name, long freeSpace, long totalSpace)
{
this.driveName = name;
this.currentFreeSpace = freeSpace;
this.currentTotalSpace = totalSpace;
}
public string Name
{
get { return this.driveName; }
}
public long FreeSpace
{
get { return this.currentFreeSpace; }
}
public long TotalSpace
{
get { return this.currentTotalSpace; }
}
}
public delegate void DiskSpaceWarningEventHandler(object sender,
DiskSpaceWarningEventArgs e);
public class DiskSpaceMonitor
{
public event DiskSpaceWarningEventHandler DiskSpaceWarning;
private decimal threshhold;
public DiskSpaceMonitor()
{
// Retrieve threshhold to fire event from configuration file.
try
{
NameValueCollection settings = ConfigurationManager.AppSettings;
this.threshhold = Convert.ToDecimal(settings["Threshhold"]);
}
// If there is no configuration file, provide a default value.
catch (ConfigurationErrorsException)
{
this.threshhold = 10m;
}
catch (InvalidCastException)
{
this.threshhold = 10m;
}
}
public void CheckFreeSpace()
{
// Get drives present on system.
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
if (drive.IsReady)
{
if (drive.TotalFreeSpace/drive.TotalSize <= this.threshhold)
OnDiskSpaceWarning(new DiskSpaceWarningEventArgs(drive.Name,
drive.TotalFreeSpace, drive.TotalSize));
}
}
}
protected void OnDiskSpaceWarning(DiskSpaceWarningEventArgs e)
{
if (DiskSpaceWarning != null)
DiskSpaceWarning(this, e);
}
}
이 예제에서는 EventArgs 클래스를 사용하여 이벤트 데이터를 제공하는 대신 DiskSpaceWarningEventArgs라는 사용자 지정 이벤트 데이터 클래스를 정의합니다. 이 클래스는 드라이브 이름과 함께 드라이브의 전체 공간 양과 사용 가능한 공간 양을 이벤트 처리기에 제공합니다. 이 예제에서는 이벤트 시그니처를 나타내는 대리자인 DiskSpaceWarningEventHandler도 정의합니다.
DiskSpaceMonitor 클래스는 DiskSpaceWarning 이벤트를 정의하고 이 이벤트를 발생시키는 OnDiskSpaceWarning 메서드도 제공합니다. OnDiskSpaceWarning 메서드는 CheckFreeSpace 메서드가 드라이브의 사용 가능한 공간이 구성 파일에 정의된 비율보다 적거나 같음을 감지하면 이 메서드에 의해 호출됩니다.