PROGRAMMING WORKSHOP

Skip Navigation Links. Skip Navigation Links.

VB.Net |
LINQ & LAMBDA Expression| delegate,RaiseEvents, Event,EventHadler

Delegate개체가 메소드(함수혹은 섭프로시져)를 대신하여 호출해준다
단 호출하는 매소드와 매개변수와 돌려주는 값이 같아야 한다는
조건만 지키면 어떤 매소드든 대신 호출할수 있다...그리고 대표적인
Delegate의 사용은 이벤트프로시져라고 한다.. 뭔가 알듯말듯하다
그냥 직접 매소드를 부르면 될 것이지 왜 중간에 대리인이라는 개체를 세워놓고 이짓을 할까??
도대체 뭐가 편하다는 것이야..
꼭필요한 경우를 하나 만들어 보도록 하자..
그러면 ..아하..그렇다면 이런데 써먹으면 되겠구나..라는 생각이 들것이다
어떤 개체이던 이벤트가 발생한다
만약에 어떤 개체가 1에서 부터 100까지 차례대로 합계를 낸다고 치자
1+1 한번 계산했다..이 순간이 이벤트인 것이다
2+1 또 한번 계산했다..이 순간도 이벤트인것이다
계산을 한번 할때마다 이벤트라고 하는 것이 발생한다
문제는 이 이벤트를 활용할 것인가..말것인가이다!!
예를 들어 엑셀에서 워크시트를 한장 삽입했다
한번 삽입하는 순간 이벤트가 발생한 것이다
또 한장 삽입했다 이 순간 이벤트가 발생한 것이다
시트의 범위에 값을 변경했다 이 순간 또 이벤트라고 하는 것이 발생한 것이다
문제는 이 이벤트 발생 순간을 매소드(Handler) 와 연결을 할 것인가
말것인가??를 결정하는 것이 개체를 만드는 사람이 할 일이다
엑셀에서는 시트를 한장 삽입할때마다 발생하는 이벤트를 매소드와 연결한 것이다
이것이 여러분이 그냥 생각없이 사용하는 엑셀의 시트를 삽입할때 통합문서개체에서
이벤트를 아래와 같은 Workbook_NewSheet 라는 이벤트프로시져에 연결을 해 놓은 것이다

Private Sub Workbook_NewSheet(ByVal Sh As Object)

End Sub

이것은 내용도 없고 아무것도 없다..
이것이 Delegate라고 보시면 된다
VBA의 이벤트프로시져와 VB.Net과는 조금 개념이 다르지만
Delegate가 어떤때 왜 필요한가..를 이해하는데는 도움이 되는 것이다
이것을 다른 개발자가 사용을할지 안할지는 개체를 개발하는 사람입장에서는
알수가 없다..언제 사용할지, 혹은 사용하지도 않을지..
그냥 그러나 이럴때 사용하면 좋겠군..하고 만들어 놓는 것이다
위의 경우..시트가 삽입될때 어떤 사람은 특정통합문서에서는 시트를
추가하지 못하게 할수도 있을 것이고..
어떤 작업을 하게 할수도 있을 것이고, 그것은 엑셀개발자마음대로인것이다

그래도 감이 안온다..
그냥 직접 프로시져나 함수를 호출하면 되지..라는 생각이 남는다
실은 Lambda 표현식,Delegate, LINQ, extention method, interface,event등등의 단어들이
똑떨어지게 설명하기가 무척 힘든 부분이다, 서로 상호간 의존적 발전을 하는 것이고
이런 것들을 조합하여 가는 것이 LINQ 언어가 되는 것
delegate라는 것을 좀더 이해해 보도록 하자

예를 들어서
여러분이 사용하는 소루션에 시간차로 무언가를 하는 일이 있다고 치자
시간을 걸어 놓고, 약 1분을 걸어 놓고
10초간격으로 증권사의 어떤 정보를 갱신시킨다고 할수도 있고
20초간격으로 어떤 기계만을 작동시켰다가, 껐다가 하기도 할수도 있을 것이고
10초간격으로 빨강색을 파랑색으로 바꿔주어야 하는 일도 할수 있을 것이고..
30초간격으로 께임에서 폭탄이 폭파되게 할 수도 있을 것이고..
그러면 여기에서 공통적으로 하는 작업은 무엇일까??
시간을 가는 것을 카운트하는 작업이 공통적인 작업이 될수 있을 것이다
이때 크래스모듈에 시간만 관리하는 것을 만들수 있을 것이고
이 크래스모듈을 각각의 일, 증권사의 일, 기계를 작동하는 일, 색깔을 바꿔주는 일
모든 일에 도움을 주는 크래스모듈이고 개체가 될수 있는 것이다

Class myTimer
Public Sub Go(ByVal dblDuration As Double, ByVal dblInterval As Double)
	Dim dblStart As Double = DateAndTime.Timer
	Dim dblElapsed As Double = 0
	Dim dblUpToNow As Double = 0
	Do While dblElapsed < dblDuration
		If dblElapsed > dblUpToNow + dblInterval Then
			dblUpToNow += dblInterval
		End If
		dblElapsed = DateAndTime.Timer - dblStart
	Loop
End Sub
End Class

myTimer 라고 이름을 지은 크래스를 하나 만들고
Go라는 메소드가 하나 있다
Go라는 메소드는 타임을 얼마동안 관측할지의 시간과 시계가 똑딱거리고 가듯이
얼마마다 똑딱거리라는 인터벌, 두개의 매개변수를 주었다
그럼, 이 개체는 주어진 인터벌 마다 똑딱거리면서 간다
그러다가 주어진 시간이 모두 지나면 정지 된다
뭐야...이것 별것 아니잖아...위의 상태는 아무의미도 없다
그냥 주어진 시간이 끝나버리고 말면 그만이다..

그런데 여기에서 10초간격으로 똑딱거린다고 할때
이 똑딱거림을 개체를 사용자에게 알려주는 방법이 없을까??????
이때 Delegate가 나타난다..
그냥 Delegate는 아무짓도 하지 않는다..
그냥 Delegate라고 하는 여기에서는 특별하게 Event라고 부를 뿐이다
이것을 이 크래스를 개체로 생성하여 사용하는 사용자에게 작업내용을
알아서 하라고 프레임만 만들어주면 된다
바로 이 부분이다...작업내용은 없다, 이것은 각자가 알아서 해라!!!
그러기 위하여서는 Delegate라는 것을 위의 크래스에 표현을 해줘야 할 것이다
아직 이해가 잘 가지 않는다, 좀더 가보자..위의 크래스를 소비해 보는 것이다
아래와 같이

Class myTimer
Public Event DoSomethingHere(ByVal Countdown As Double)
Public Event AllDone()
Public Sub Go(ByVal dblDuration As Double, ByVal dblInterval As Double)

	Dim dblStart As Double = DateAndTime.Timer
	Dim dblElapsed As Double = 0

	Dim dblUpToNow As Double = 0
	Do While dblElapsed < dblDuration
		If dblElapsed > dblUpToNow + dblInterval Then
			dblUpToNow += dblInterval
		End If
		dblElapsed = DateAndTime.Timer - dblStart
	Loop
End Sub
End Class

위의 Event라는 키워드,
이것이 Delegate를 이벤트용으로 특별히 만든 단어인것
작업내용은 없다, 그냥 프로시져명과 매개변수만 선언해 놓은 것이다
아하...이 개체는 이벤트라는 구성원이 만들어진 셈이다
엑셀에서 워크시트개체의 다양한 이벤트를 선택하여 사용하는 것을 기억하시면 된다

그런데 위와 같이만 해놓으면 허당이다
10초마다 똑딱거리고 알려 주어야 한다는 것..
그럼 10초마다 Event 라는 delegate에게 뭔가 매개변수를 전달한다
즉 시간 되었어요..일하세요..라고 정보를 전달하게 해야 한다
두줄만 더 추가해보자

Class myTimer
Public Event DoSomethingHere(ByVal Countdown As Double)
Public Event AllDone()
Public Sub Go(ByVal dblDuration As Double, ByVal dblInterval As Double)

	Dim dblStart As Double = DateAndTime.Timer
	Dim dblElapsed As Double = 0

	Dim dblUpToNow As Double = 0
	Do While dblElapsed < dblDuration
		If dblElapsed > dblUpToNow + dblInterval Then
			dblUpToNow += dblInterval
			RaiseEvent DoSomethingHere(dblDuration - dblUpToNow)
		End If
		dblElapsed = DateAndTime.Timer - dblStart
	Loop
	RaiseEvent AllDone()

End Sub
End Class

아하...RaiseEvent....말그대로 이벤트를 일으켜라!!!
시간을 순환하면서..어떤때가 될때(매개변수로 전달받은 인터벌) 이벤트를
일으켜 준다는 것
그리고 다 끝난 다음에 AllDone이라는 끝났음을 알려주는 이벤트를
일으켜 주게 한 것이다
크래스가 하나 설계가 끝난 것이다
그럼 이것을 소비하는 소비자 입장에서 어떻게 사용하는 가를 보면 된다
여기에서는 이렇게 활용해 보자
빈탕의 폼을 열고 버튼을 크릭하면 위의 크래스가 개체로 생성되고
이벤트를 받아서 사용하여 똑딱거릴때마다 버튼을 하나,하나 만들어 간다
시간이 끝날때까지..



이렇게 소비하는 사람마음대로 활용하는 것이다
버튼을 그릴수도 있고, 문자를 쓸수도 있고, 또 다른 의미있는 정보를
발생하게 할수도 있고..
Form 모듈에서 소비하도록 해보자

Public Class Form1
    WithEvents oX As myTimer' 크래스개체를 담을 변수를 만들고

    Private Sub Form1_Load() Handles MyBase.Load
        Button1.Text = "시작"
        oX = New myTimer ' 폼이 로딩되면서 사용라려는 개체를 생성하고
    End Sub
End Class

폼도 하나의 크래스라는 것은 이미 다 아시는 것이고..
전역 변수에 위에서 만든 크래스 myTimer라는 것을 사용할 변수를 하나 만드는데
이때 WithEvents 라는 키워드를 사용하면
myTimer라는 크래스에서 이벤트(Delegate)를 배포한다면 이것을 사용하겠다!!!
라는 명령을 준 것이다..
그럼 뭐가 변하냐 하면 아래의 그림과 같이 위의 크래스에서 만든
Event목록이 나타나는 것이다



아이콘이 어떤 표시인가..Delegate라는 표시(자물통표시)가 보이지 않는가..
아무튼 WithEvents로 변수를 선언하면 이 이벤트를 아래그림의 오른쪽목록에서
해당 이벤트를 선택하여 하고 싶은 일을 각자가 께임을 하던
버튼을 만들던..색깔을 바꾸던..변하는 시간에 따라서 알아서
흥미롭게 만들면 되는 것이다
이제 Delegate가 감이 오실것이다..
아하 ... 뭔가 할수 있는 형식만 만들어주고..나머지는 소비자(또 다른 상위 개발자)가
활용하라는 것....

EventHadler라고 하면 바로 Delegate가 호출한 프로시져가 되는 셈인 것이다
각자가 만든 프로시져..
VBA에서 익숙한 워크시트의 이벤트프로시져, 워크북의 이벤트프로시져가
바로 이벤트핸들러라고 부르는 것
실은 모든 용어라고 하는 것이 각자 제마음대로 만드는 것이고
개념은 같다..그러니 용어를 외우지 말고 개념을 알아야 한다
같은 개념을 쟈바에서는 이렇게 이야기 하고 C++에서는 저렇게 이야기할뿐이다
그리고 VB.Net에서는 또 요렇게 이야기하고..

영어의 단어도 사전의 것을 딸딸딸 외우는 것이 아니고
단어의 깊은 의미를 아는 것이 영어를 잘하는 것도 같은 이야기다

개체를 생성하고 사용하는 방법은
엑셀에서 워크시트의 개체나 통합문서개체의 이벤트프로시져를 사용하는 것이나 같겠지..
너무 깊은 것을 이야기 하니..지루하실 것이다
다음 페이지에서는 실제로 LINQ를 활용해 보면서..관련된 이야기들을
해나가는 것으로 하도록 하자

***[LOG-IN]***