블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2794)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (11)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
부모 폼과 자식 폼이 있다; 자식 폼에서 A라는 버튼을 클릭했을 때; B라는 텍스트 박스의 내용을 부모 폼의 C라는 텍스트 박스에 표시하고 싶다; 그 방법은?

물론; 가장 간단한 방법은 private으로 선언되어 있는 C라는 텍트스 박스를 public으로 선언하고; 자식 폼에서 직접 이 텍스트 박스에 접근하여; 값을 대입하는 방법이 있습니다;

하지만; 개인적으로 이 방법은 C#이 지향하는 OOP(Object-oriented paradigm)를 위배하고; 깔끔하지 못한 방법으로 별로 권장하고 싶지 않네요;

개인적으로 권장하는 것은 이벤트(event)를 이용하는 것 입니다; 이벤트는 단순히 폼 간의 어떤 데이터를 주고 받을 수 있을 뿐만 아니라; 서로 다른 클래스 간의 데이터 전송에도 유용하며, 데이터를 구조체 형식으로도 넘길 수 있는 등 다양한 장점이 있지요; 무엇보다, OOP를 준수하면서도; 깔끔한 코드를 유지할 수 있다는 것에 후한 점수를 주고 싶군요;

이 이벤트를 구현하는 방법에 가장 핵심이 되는 내용은 바로 delegate 입니다.
C++/MFC, java 등 다른 언어에 능숙한 사람들 대부분이 C#에 금방 적응하게 됨에도 불구하고; 그나마 C#에서 가장 당황하는 개념이 delegate가 아닐까 싶네요; (나만 그런가?;)

delegate는 한글로 굳이 번역하자면; 대리자라고 하는데; C#이 다른 언어와 차별성을 가지는 중요한 몇 몇 이슈 중 하나가 이 녀석의 존재라고 생각합니다;

단어 뜻으로만 이해하자면; 어려우니까; 서두에 언급한 자식 폼에서 부모 폼으로 텍스트를 전달하는 예제를 통해; delegate의 역할을 이해해보죠;

이미 언급했지만; 자식 폼에서 부모 폼으로 데이터를 전달할 때, 이벤트를 이용하기로 하였는데; 이벤트에서 가장 기본적인 사실은; 이벤트를 발생하는 곳이 있으면, 이벤트를 받는 쪽도 있어야 된다는 것입니다;

따라서, 자식 폼에는 이벤트를 발생시키는 녀석을 정의하고, 부모 폼에서는 이벤트를 받는 녀석을 정의해야 된겠지요. 이미 C#을  이용해 윈 폼 프로그래밍을 해본 사람이라면; 폼에 버튼을 붙이고; 클릭 이벤트를 추가해서; 버튼을 클릭하면; 메시지 박스로 "Hello, World!" 정도는 경험이 있을 것 입니다;

이 때, 버튼도 우리가 예로 들려는 자식 폼과 같습니다; 버튼이 이벤트를 발생시키고, 부모 폼에서 버튼 이벤트를 받아, 거기서 메시지 박스를 띄운 것이기 때문이지요;

자 이벤트를 정의하는 과정은 다음과 같습니다;
사용자 삽입 이미지

클래스 ChildFormEventArgs는 이벤트 데이터가 들어 있는 클래스에 대한 기본 클래스인 EventArgs를 상속 받아 구현하였습니다. 우리는 자식 폼에서 부모 폼으로 텍스트를 전송할 목적이므로, 기본 클래스에 message란 속성을 추가하였구요;

그리고 그 아래 이벤트 대리자(delegate)를 선언하는데, 대리자를 통해 넘기는 파라미터에 주목해봅시다;
ChildFormEventArgs는 앞에 언급한대로 이벤트 데이터 이고, object sender는 뭘까요?

이벤트를 발생 시킨 주체입니다; 우리의 예에서는 바로 자식폼이 되겠지요;

이벤트를 위한 대리자를 선언했으면; 자식 폼에 이 이벤트를 발생시키기 위한 코드를 구현해야 합니다;
사용자 삽입 이미지

이벤트 선언부를 눈여겨 보세요;

이에 앞서 선언한 delegate에 이벤트를 위한 엑세스 한정자인 event를 붙였습니다; 그리고 파생 클래스에서 이 이벤트를 일으키거나 override 할 수 있도록 protected와 virtual 키워드를 붙였지요;

그리고 그 아래 정의된 메소드는 자식 폼에 추가한 버튼을 클릭하면 호출되는 녀석; 이미 알고 있듯이; 우리는 버튼을 클릭했을 때, 자식 폼에 있는 텍스트 박스(txtSentMessage)에 적힌 텍스트를 부모 폼에 전달하기 위함이므로; 앞서 정의한 event를 발생시킬 수 있는 NotifyEvent를 호출하도록 하였습니다;

그럼, 이제 부모 폼에서 이벤트를 받을 수 있도록 구현해보죠;
사용자 삽입 이미지

부모 폼의 생성자(constructor)에 자식폼의 메모리를 할당하고; 이벤트를 받기 위해 OnNotifyParent이벤트 핸들러를 추가합니다;

자, 여기서 대리자(delegate)의 역할을 이해할 수 있습니다. 자식 폼에서는 결코 부모 폼의 child_OnNotifyParent 메소드를 직접적으로 호출하지 않습니다. 단지, 이벤트로 정의한 OnNotifyParent(delegate)를 구현하였고; 이를 이용해 이벤트를 발생시키는 NotifyEvent 메소드만 구현했을 뿐이지요; 하지만 OnNotifyParent는 대리자란 명칭에 걸맞게; NotifyEvent가 호출되면; 간접적으로 child_OnNotifyParent 해줬습니다;

이 때 이벤트 데이터를 전달해주는 ChildFormEventArgs를 통해 자식폼의 텍스트 박스에 적힌 텍스트를 가져올 수 있네요;

다시, 정리하자면 이렇습니다.
1. 이벤트는 이벤트를 발생시키는 곳이 있으면, 발생한 이벤트를 듣는 곳도 있다;
2. 이벤트는 이벤트를 발생시키는 곳과 발생한 이벤트를 듣는 곳을 잇기 위한 대리자(delegate)로 구현한다.

delegate란 개념은 단지; 이벤트를 구현할 때만 쓰이지 않습니다; 제가 오래 전에 블로그에 쓴 C#에서 크로스 쓰레드 문제에서도 언급된 적이 있습니다. 사실 저도 저 때 delegate 개념이 구체화 되지는 않았습니다; 어렴풋이 이해만 했었고; 단지 저런 상황이 생기면; 다시 써먹기 위해 남겼을 뿐이지요..;

혹시나 필요하신 분들이 있을까; 아티클에 설명한 예제의 소스 코드를 첨부합니다;



반응형
Posted by blueasa
, |