순서

I. Event
II. Event Handler 직접 구현 예제
III. System 제공 EventHandler 구현 예제
IV. System 제공 EventHandler로 인자 넘기기 예제

 


I. Event

Event 객체란
" 특정 상황이 발생하면 B라는 함수를 호출해줘 " 의
명령을 받아 해당 상황이 발생하는지 감시하며 옵저버(Observer)역할을 하는 객체이다.

Event 객체는 상황 발생 시 다양한 method들을 실행 할 수 있는데
항목들을 관리하는 주체를 EventHandler 라고 한다.
이 항목들은 외부 객체가 원하는 항목을 등록하게 된다.

UI에서 버튼을 누르면 팝업창이 띄워지는 것과 같은 방식처럼
특정 행동이 발생했을 때 원하는 함수를 실행시키는 것이다.

이때 실행시켜주는 EventHandler 를 "게시자 (Publisher)"
행동을 등록하는 객체를 "구독자 (Subscriber)" 라고 한다.

물론, 그냥 if 와 함수 콜로 구현할 수 있지만, Event로 구현하게 되면
Event 발생시점을 체크하기 위해 계속 확인 할 필요가 없고'
서로 독립적인 구조를 갖도록 구현할 수 있기 때문에 사용한다.

 


II. Event Handler 직접 구현 예제

문법적인 순서는 다음과 같다.

1. 행동들(methods)를 담을 delegate 생성
2. event 한정자를 갖고 delegate 객체를 형식으로 갖는 event변수 생성
3. event 변수에 delegate(method) 등록

using System;

namespace EventApp {
  class CMyPublisher {
    // delegate 객체 정의 (무조건 void 형식)
    public delegate void MyEventDele();
    
    // delegate 형식으로 handler 객체 정의
    public event MyEventDele EMyHandler;
    
    // ? : Null이 아니라면의 뜻
    // 버튼 눌리는 등의 이벤트 발생하면 호출되고 Invoke로 이벤트 실행
    public void someThingHappen() => EMyHandler?.Invoke();
  }

  class CMain {
    static void Main() {
      CMyPublisher myP = new CMyPublisher();
      
      // printPush라는 행동을 EventHandler에 +로 등록한다.
      myP.EMyHandler += new CMyPublisher.MyEventDele(printPush);
      
      // 원래는 외부에서 일어나지만 테스트 불가능하여 직접 호출해줌
      myP.someThingHappen();
      
      // 행동 삭제(탈퇴)를 원한다면
      myP.EMyHander -= printPush;
    }

    static public void printPush() {
      Console.WriteLine("Push!");
}}}

 

 


III. System 제공 EventHandler 구현 예제

System에서 제공한 EventHandler를 사용하려면 void delegate가 아닌

public delegate void EventHandler(Object sender, EventArgs e)
        * sender : 이벤트가 발생한 객체, publisher 자신의 참조

가 기본적으로 delegate로 저장되어 있어 함수 정의에 주의한다.

 

using System;

namespace EventApp2 {
  class CSysEventPublisher {
   // delegate 형식 : EventHandler
    public event EventHandler myEHandler;
    
    public void somethingHappened() {
      // 코드 아래 설명 참고
      myEHandler?.Invoke(this, EventArgs.Empty)
    }
  }
  
  class CMain {
    static void Main() {
      CSysEventPublisher CSysP = new CSysEventPublisher();
      
      CSysP.myEHandler += new EventHandler(printPush);
      
      CSysP.somethingHappened();
    }
    
    public static void printPush(object sender, EventArgs e) {
      Console.WriteLine("Push!");
}}}


delegate 형식인 EventHandler를 사용하기 위해서 아래와 같이 사용하였다.

myEHandler?.Invoke(this, EventArgs.Empty)
 -> Invoke (Object sender, EventArgs e) 형태

 

 

sender : 이벤트가 발생하는 객체 ( 자기자신을 넘김 )
EventArgs : EventHandler에서 제공하는 인자 형식으로 void 형식은 Empty를 사용한다.

 


 

IV. System 제공 EventHandler로 인자 넘기기 예제

 

만약 인자를 실제로 넘기고 싶다면 어떻게 사용할까?

delegate에 등록된 함수는 delegate에 인자를 넣어 등록된 함수로 전달하는 형식이다.

핵심 1. EventArgs를 상속받는 Data 객체를 직접 만들어주어야 한다.
핵심 2. 이벤트 발생(delegate호출)시 해당 데이터 객체를 통째로 넘겨 실행
핵심 3. 호출된 개별 method들은 통째로 받은 데이터 객체를 알아서 사용

using System;

namespace ConsoleApp18 {
    // 핵심 1. EventArgs를 상속받는 Data 객체 만들어줘야함. 
    class CMyEventData : EventArgs {
        public string myEventData;
        public CEventData(string myEventData) => this.myEventData = myEventData;
    }

    class CPublisher {
        public event EventHandler EMyEventHandler;

        public void somethingHappened() {
            // 핵심 2. Event 객체를 통째로 delegate를 통해 전달함.
            EHMyEventHandler?.Invoke(this, new CMyEventData("push event"));
        }
    }
    
    public class CMain {
        static void Main() {
            CPublisher P = new CPublisher();
            P.EMyEventHandler += (doAction);
            
            myBtn.somethingHappened();
        }
        
        // 핵심3. Event Data 객체가 "e"로 통째로 들어옴
        public static void doAction(object sender, EventArgs e) {
            string s = ((CEventData)e).myEventData;
            Console.WriteLine(((CEventData)e).myEventData);
        }
    }
}

 

+ Recent posts