Skip to content

Instantly share code, notes, and snippets.

@grimmdev
Created October 7, 2015 07:56
Show Gist options
  • Save grimmdev/b9db774ffedfae563e6f to your computer and use it in GitHub Desktop.
Save grimmdev/b9db774ffedfae563e6f to your computer and use it in GitHub Desktop.
Helpful Utility for Games in Unity
using System;
using System.Linq;
public static class Messenger
{
public static void AddListener(string eventType, Action handler)
{
MessengerInternal.AddListener(eventType, handler);
}
public static void AddListener<TReturn>(string eventType, Func<TReturn> handler)
{
MessengerInternal.AddListener(eventType, handler);
}
public static void RemoveListener(string eventType, Action handler)
{
MessengerInternal.RemoveListener(eventType, handler);
}
public static void RemoveListener<TReturn>(string eventType, Func<TReturn> handler)
{
MessengerInternal.RemoveListener(eventType, handler);
}
public static void Broadcast(string eventType)
{
Messenger.Broadcast(eventType, MessengerInternal.DEFAULT_MODE);
}
public static void Broadcast<TReturn>(string eventType, Action<TReturn> returnCall)
{
Messenger.Broadcast<TReturn>(eventType, returnCall, MessengerInternal.DEFAULT_MODE);
}
public static void Broadcast(string eventType, MessengerMode mode)
{
MessengerInternal.OnBroadcasting(eventType, mode);
Action[] invocationList = MessengerInternal.GetInvocationList<Action>(eventType);
Action[] array = invocationList;
for (int i = 0; i < array.Length; i++)
{
Action action = array[i];
action();
}
}
public static void Broadcast<TReturn>(string eventType, Action<TReturn> returnCall, MessengerMode mode)
{
MessengerInternal.OnBroadcasting(eventType, mode);
Func<TReturn>[] invocationList = MessengerInternal.GetInvocationList<Func<TReturn>>(eventType);
foreach (TReturn current in (
from del in invocationList
select del()).Cast<TReturn>())
{
returnCall(current);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
internal static class MessengerInternal
{
public class BroadcastException : Exception
{
public BroadcastException(string msg) : base(msg)
{
}
}
public class ListenerException : Exception
{
public ListenerException(string msg) : base(msg)
{
}
}
public static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
public static readonly MessengerMode DEFAULT_MODE = MessengerMode.REQUIRE_LISTENER;
public static void AddListener(string eventType, Delegate callback)
{
MessengerInternal.OnListenerAdding(eventType, callback);
MessengerInternal.eventTable[eventType] = Delegate.Combine(MessengerInternal.eventTable[eventType], callback);
}
public static void RemoveListener(string eventType, Delegate handler)
{
MessengerInternal.OnListenerRemoving(eventType, handler);
MessengerInternal.eventTable[eventType] = Delegate.Remove(MessengerInternal.eventTable[eventType], handler);
MessengerInternal.OnListenerRemoved(eventType);
}
public static T[] GetInvocationList<T>(string eventType)
{
Delegate @delegate;
if (!MessengerInternal.eventTable.TryGetValue(eventType, out @delegate))
{
return null;
}
if (@delegate != null)
{
return @delegate.GetInvocationList().Cast<T>().ToArray<T>();
}
throw MessengerInternal.CreateBroadcastSignatureException(eventType);
}
public static void OnListenerAdding(string eventType, Delegate listenerBeingAdded)
{
if (!MessengerInternal.eventTable.ContainsKey(eventType))
{
MessengerInternal.eventTable.Add(eventType, null);
}
Delegate @delegate = MessengerInternal.eventTable[eventType];
if (@delegate != null && @delegate.GetType() != listenerBeingAdded.GetType())
{
throw new MessengerInternal.ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, @delegate.GetType().Name, listenerBeingAdded.GetType().Name));
}
}
public static void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved)
{
if (!MessengerInternal.eventTable.ContainsKey(eventType))
{
throw new MessengerInternal.ListenerException(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know about this event type.", eventType));
}
Delegate @delegate = MessengerInternal.eventTable[eventType];
if (@delegate == null)
{
throw new MessengerInternal.ListenerException(string.Format("Attempting to remove listener with for event type {0} but current listener is null.", eventType));
}
if (@delegate.GetType() != listenerBeingRemoved.GetType())
{
throw new MessengerInternal.ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, @delegate.GetType().Name, listenerBeingRemoved.GetType().Name));
}
}
public static void OnListenerRemoved(string eventType)
{
if (MessengerInternal.eventTable[eventType] == null)
{
MessengerInternal.eventTable.Remove(eventType);
}
}
public static void OnBroadcasting(string eventType, MessengerMode mode)
{
if (mode == MessengerMode.REQUIRE_LISTENER && !MessengerInternal.eventTable.ContainsKey(eventType))
{
throw new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but no listener found.", eventType));
}
}
public static MessengerInternal.BroadcastException CreateBroadcastSignatureException(string eventType)
{
return new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but listeners have a different signature than the broadcaster.", eventType));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment