본문 바로가기

Development/C#

Dynamically Raise Event using Reflection

Introduction

C# 에서의 이벤트는 해당 이벤트가 선언된 클래스에서만 호출할 수 있는 특수한 종류의 Multicast Delegate의 형태로서, 아래와 같이 이벤트가 정의된 클래스를 상속 받아 구현 했다 하더라도 이벤트를 직접 호출할 수 는 없습니다.


이를 해결하기 위한 일반적인 방법으로 아래와 같이 부모객체에 해당 이벤트를 호출 할 수 있는 메서드를 미리 정의 함으로서 이벤트를 호출 하는 방법을 사용합니다.


그런데 만약 부모의 소스코드에 접근 할 수 없는 상황(예: 라이브러리에서 제공하는 객체를 상속받아 구현하는 경우)이거나 외부객체의 이벤트를 강제로 호출하고자 할 경우에 여러가지 문제가 발생할 수 있습니다. 이번시간에는 외부 혹은 내부에 정의된 이벤트에 접근하고 해당 이벤트를 직접 호출하는 방법에 대해 소개합니다.

Create RaiseEventHelper

외부에서 정의된 이벤트를 호출하기전에 먼저 개발자가 이벤트를 정의 했을때 내부적으로 어떠한 변화가 있는지를 확인 해볼 필요가 있습니다. 먼저 아래와 같이 간단한 이벤트가 정의된 코드를 빌드한 후 Windows SDK에서 제공하는 IL DASM을 이용해 작성한 코드가 어떻게 변화 했는지 확인 해 보겠습니다.

왼쪽은 이벤트를 정의 하기 전의 어셈블리이며. 오른쪽이 위 코드를 빌드한 어셈블리입니다. 단순히 이벤트한줄만 추가했을 뿐인데 내부적으로 여러개의 멤버들이 추가로 생성된것을 확인 할 수있습니다.

추가된 항목중에 관심있게 살펴봐야 하는 것은 DummyEvent 필드로, 코드에서 정의한 이벤트와 같은 Delegate를 사용하고 이름까지 동일하는 것으로 보아 이벤트를 구독하거나 해지 할때 DummyEvent필드를 이용한다는것을 알 수 있습니다. 이제 이벤트가 생성되었을때 내부적으로 관리되는 Delegate가 어떻게 생성되는지 알았으므로 Reflection을 이용해 외부에서도 얼마든지 이벤트를 호출 할 수 있습니다.


간단히 코드를 설명하면 Target 객체에 EventName에 해당하는 Delegate를 검색하고 이를 구독하는 여러 메서드들을 직접 호출해주는것으로 이벤트를 호출하는것과 동일한 효과를 낼 수 있습니다. 그리고 실제 사용할 때에는 아래와 같이 사용할 수 있습니다.


이상으로 이번 포스팅을 마치며 기타 궁금하신점이나 다른 문의사항은 메일이나 댓글로 남겨주시면 답변드리도록 하겠습니다. 감사합니다.