옵저버 패턴과 유사하다고 짚고 넘어가겠습니다.
이번 포스팅에서는 이벤트 관리 시스템을 제네릭 타입을 사용하여 구현하였습니다.
제네릭을 사용함으로써 다양한 타입의 데이터를 유연하게 처리할 수 있으며, 여러 이벤트에 맞는 데이터를 효율적으로 전달하는 방법에 대해 알아보겠습니다.
제네릭을 사용한 EventManager 구현
public class EventArgs<T> : EventArgs
{
public T Data { get; }
public EventArgs(T data)
{
Data = data;
}
}
📋
EventArgs<T>는 제네릭 타입을 사용하여 데이터를 담을 수 있습니다. 이벤트가 발생할 때, 특정 타입의 데이터를 전달할 수 있도록 합니다.
EventArgs를 상속받는 이유는 .NET 프레임워크와 C#의 이벤트 시스템에서 표준화된 패턴을 따르기 위해서입니다. C#에서 이벤트를 정의할 때 주로 이벤트 핸들러는 두 가지 파라미터를 가집니다.
이벤트를 발생시키는 객체(주체) - Sender
이벤트의 추가 정보를 담은 객체 - EventArgs
이벤트 관리 시스템 - EventManager 클래스
// 이벤트 타입 정의
public enum EventType
{
PlayerMoved, // 플레이어가 이동할 때의 이벤트
}
📋
public static class EventManager
{
// 이벤트 리스너를 관리하는 딕셔너리
private static readonly Dictionary<EventType, Action<EventArgs<object>>> _eventDictionary
= new ();
// 리스너 등록
public static void AddListener(EventType eventType, Action<EventArgs<object>> listener)
{
if (_eventDictionary.ContainsKey(eventType))
{
_eventDictionary[eventType] += listener;
}
else
{
_eventDictionary[eventType] = listener;
}
}
// 리스너 제거
public static void RemoveListener(EventType eventType, Action<EventArgs<object>> listener)
{
if (_eventDictionary.ContainsKey(eventType))
{
_eventDictionary[eventType] -= listener;
}
}
// 이벤트 발생
public static void PostNotification<T>(EventType eventType, EventArgs<T> args)
{
if (_eventDictionary.TryGetValue(eventType, out var listeners))
{
// 제네릭 타입을 object로 캐스팅하여 전달
listeners?.Invoke(args as EventArgs<object>);
}
}
}
📋
- AddListener: 특정 이벤트 타입에 리스너를 등록합니다. 리스너는 해당 이벤트가 발생하면 실행되는 콜백 함수입니다.
- RemoveListener: 특정 이벤트 타입에 등록된 리스너를 제거합니다.
- PostNotification: 이벤트가 발생했을 때, 등록된 모든 리스너에게 알림을 보내고 데이터를 전달합니다.
사용예시
플레이어가 이동하는 이벤트가 발생할 때,
private void MovePlayer(Vector3 direction)
{
transform.position += direction;
// 플레이어 이동 이벤트 발생
EventManager.PostNotification(EventType.PlayerMoved, new EventArgs<Vector3>(transform.position));
}
📋
UI에서는 플레이어가 이동한 이벤트를 처리합니다.
private void OnEnable()
{
//이벤트 등록
EventManager.AddListener(EventType.PlayerMoved, OnPlayerMoved);
}
private void OnPlayerMoved(EventArgs<object> args)
{
Vector3 position = (Vector3)args.Data;
Debug.Log($"Player moved to: {position}");
}
📋