출처 : www.hoonsbara.com
오늘은 델리게이트와 이벤트에 대해 설명해보도록 하겠다.
이벤트(Event)
필자가 아는 선배 중 한 분의 어릴적 꿈이 로봇 만화영화에 자주 등장하는 “김박사”였다고 한다. 그래서, 그
선배는 어릴적 어머니께 “엄마, 나는 커서 김박사 될래~”라고 말하곤 했다고 한다. 그럴때마다, 선배의 어머니께서는 “너는 김박사가 될 수
없단다.”라고 말씀하셨다고 한다. 그 선배의 성이 김씨가 아닌 박씨였기 때문이다. 그래도 그 선배는 그 꿈을 버리지 않았다고 한다. 오늘은 그
선배의 아름다운(?) 동심을 생각하며, 김박사 예제를 만들어보도록 하겠다.
로봇이 전투를 하러 나갔을 때, 적들과 맞서서 한참을 싸운 우리의 로봇은 여러곳이 고장나게 된다. 이렇게 되면,
로봇은 김박사에게 “박사님, 수리해주세요”라고 메시지를 날리게 되고, 김박사는 로봇을 원격으로 수리하는 것이다.
여기에서, 로봇이 부상당하면, 로봇은 김박사에게 수리를 요청하는 이벤트를 발생시키고, 김박사는 원격으로 로봇을
수리하는 것이다.
Event.cs |
using System
; . . . // 로봇이 보내는 메세지 매개인자. public
class RobotMessageEventArgs :
EventArgs { public
string strMessage; //
김박사에게 보낼 메세지 //
생성자 public RobotMessageEventArgs(string
message) { strMessage=message; } } . . . public class
Robot { private
string m_strName; //이름 private
string m_Color; //색깔 private int m_nEnergy; //에너지 private
General_Weapon m_generalW; //일반무기 private
Special_Weapon m_specialW; //특수무기 private
POINT m_point; //현재위치 private
int m_nPowerUP; //몇
대가 합체된 상태인지? private
WeaponMode m_WeaponMode; //현재
무기발사 모드 private static int
nRobotCount=0; //만들어진 로봇의
갯수 public delegate int ShootDelegate(int
n); //
이벤트 핸들러를 위한 델리게이트
작성 public delegate
void
RequestRepairEventHandler(object source, RobotMessageEventArgs
e); public
ShootDelegate Shoot; //
RequestRepairEventHandler 형으로 이벤트가 발생되었을때 호출될
메소드 public
event
RequestRepairEventHandler
onRequestRepairEventHandler; public Robot():this("","",new
POINT(0,0),1) { } . . . //로봇이
손상을 입었음 public
void
onDamaged() { Console.WriteLine("Robot
: 로봇이 손상을
입었습니다."); RobotMessageEventArgs
e=new RobotMessageEventArgs("박사님,
수리해주세요"); OnRequestRepairEventHandler(this,
e); Console.WriteLine("Robot
: 김박사에게 수리를
요청했습니다."); } //로봇을
진단하고 원격으로 고치는 함수 public
void
CheckNRepair() { Console.WriteLine("Robot
: 수리가
완료되었습니다."); } . . . } public
class
Dr_Kim { public static
void RemoteRepair(object obj,
RobotMessageEventArgs
e) { if(e.strMessage=="박사님,
수리해주세요") { Console.WriteLine("김박사
: 로봇으로부터 수리요청을
받았습니다."); //
이벤트 매개인자를 통해서 현재 로봇의 레퍼런스를 알 수
있다. Robot
robot=(Robot)obj; Console.WriteLine("김박사
: 원격으로 로봇을 진단하고,
수리합니다."); //로봇을
진단하고
치료함 robot.CheckNRepair(); } } } public class Battle { public
static void
Main() { Robot
robotA=new
Robot(); robotA.OnRequestRepairEventHandler +=
new
Robot.RequestRepairEventHandler(Dr_Kim.RemoteRepair); robotA.OnDamaged(); } } |
다음은 로봇이 김박사에게 메시지를 보낼 때 사용하는 이벤트 매개인자 클래스다.
// 로봇이 보내는 메세지 매개인자. public class
RobotMessageEventArgs :
EventArgs { public
string strMessage; // 김박사에게
보낼 메세지 //
생성자 public RobotMessageEventArgs(string
message) { strMessage=message; } } |
주의 깊게 봐야할 것은 “:EventArgs" 부분인데, 이것은 EventArgs 클래스를 상속받아서 사용한다는
것이다. 상속에 대한 것은 다음시간에 자세히 다루겠지만, 간단히 이야기하자면, 우리가 만드는 RobotMessageEventArgs 클래스는
EventArgs 클래스를 상속받아서, EventArgs의 기능을 사용할 수 있도록 한다는 의미이다.
다음은 델리게이트의 선언부분이다. 이벤트에 사용될 델리게이트는 두 개의 매개인자를 사용하는데, 하나는 이벤트를
발생시키는 객체를 나타내는 object 형의 변수이며, 또 다른 하나는 EventArgs를 상속받은 클래스의 객체이다.
// 이벤트 핸들러를 위한
델리게이트 작성 public delegate void
RequestRepairEventHandler (object
source, RobotMessageEventArgs e); |
다음은 위에서 만든 델리게이트 형으로 이벤트 핸들러를 선언한 것이다. 여기에서는 event라는 키워드를 사용했다는
것을 주목하자.
//
RequestRepairEventHandler 형으로 이벤트가
//발생되었을때 호출될
메소드 public
event
RequestRepairEventHandler
onRequestRepairEventHandler; |
로봇이 손상입었을 때 호출되는 함수다. 시나리오에서처럼, 로봇이 손상을 입으면, 김박사에게 수리를 요청하는
메시지를 보내는 이벤트를 발생시킨다. 위에서 말했듯이, 이벤트를 발생시킬 때 사용되는 매개인자는 두 개가 필요하다. 이벤트를 보낼 객체는 로봇
자신이므로 this 키워드를 사용하고, 이벤트의 매개인자로 사용될 RobotMessageEventArgs 객체를 생성한다. 그리고 이벤트
핸들러인 onRequestRepairEventHandler를 this 키워드와 이벤트 매개인자 e를 이용해서 호출한다.
//로봇이 손상을 입었음 public void
onDamaged() { Console.WriteLine("Robot
: 로봇이 손상을
입었습니다."); RobotMessageEventArgs
e=new
RobotMessageEventArgs("박사님,
수리해주세요"); OnRequestRepairEventHandler(this,
e); Console.WriteLine("Robot
: 김박사에게 수리를 요청했습니다."); } |
먼저 Main() 메소드를 살펴보자. 여기서는 로봇 객체를 생성하고, 로봇이 호출하는 이벤트 핸들러에 김박사의
RemoteRepair()메소드를 연결시키는 작업을 한다. 이렇게하면, 로봇 클래스에서 onRequestRepairEventHandler를
이용해 이벤트를 발생시키면, 실제로는 김박사의 RemoteRepair()메소드가 호출되는 것이다. 그리고 연산자 +=이 사용되었는데, 이것은
이전 시간에 델리게이트 합성에서 이미 설명했듯이, 하나의 델리게이트 멤버로 여러개의 메소드를 호출했었던 예제를 생각하면 될 것이다. 물론 반대는
-=이다.
public static void
Main() { Robot
robotA=new
Robot(); robotA.OnRequestRepairEventHandler +=
new
Robot.RequestRepairEventHandler(Dr_Kim.RemoteRepair); robotA.OnDamaged(); } |
다음 부분은 이벤트 핸들러를 통해서 호출된 김박사가 원격으로 로봇을 수리하는 함수이다. 이 함수에서는 이벤트
매개인자를 통해서 메시지를 확인하고, 수리를 요청하는 메시지이면, 메시지를 보낸 로봇의 CheckNRepair()메소드를 호출해서 수리하는 일을
한다.
매개인자인 obj는 이벤트를 발생시킨 객체이므로 명시적으로 Robot의 인스턴스의 레퍼런스 변수로 변환할 수
있다. 그리고, 우리가 이미 델리게이트를 공부해서 알고 있듯이, Robot클래스에서 선언한 델리게이트의 인자와 이벤트 핸들러로 사용될
RemoteRepair()메소드의 매개인자의 타입이 같음을 알 수 있다.
public class
Dr_Kim { public static void
RemoteRepair (object
obj, RobotMessageEventArgs
e) { if(e.strMessage=="박사님,
수리해주세요") { Console.WriteLine ("김박사
: 로봇으로부터 수리요청을
받았습니다."); //
이벤트 매개인자를 통해서 현재 로봇의 레퍼런스를
//
알 수
있다. Robot
robot=(Robot)obj; Console.WriteLine ("김박사
: 원격으로 로봇을 진단하고,
수리합니다."); //로봇을
진단하고
치료함 robot.CheckNRepair(); } } } |
위의 소스에서 중요부분만 간략히 그림으로 살펴보면 다음과 같다.
파란색 화살표는 이벤트가 호출되는 것이고, 빨간색 화살표는 함수를 직접 호출하는 것이다.
프로그램의 수행결과는 다음과 같다.