Skip to content

Instantly share code, notes, and snippets.

@DanPuzey
Created January 30, 2017 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanPuzey/f41d87a2137af12098055dc64caefdfd to your computer and use it in GitHub Desktop.
Save DanPuzey/f41d87a2137af12098055dc64caefdfd to your computer and use it in GitHub Desktop.
Unity3d/C# EventAggregator (Unity v5.5+)
using System;
using System.Linq;
using Diagnostics;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Events
{
public static class EventAggregator
{
#region Scene-load autoflush
static EventAggregator()
{
SceneManager.sceneLoaded += SceneLoaded;
}
private static void SceneLoaded(Scene arg0, LoadSceneMode arg1)
{
FlushStaleListeners();
}
#endregion
private class WeakListener
{
public WeakListener(UnityEngine.Object listener, object handler)
{
Listener = new WeakReference(listener);
Handler = handler;
}
public readonly WeakReference Listener;
public readonly object Handler;
public bool IsAlive
{
get
{
return Listener.IsAlive && (Listener.Target as UnityEngine.Object) != null;
}
}
}
private static Dictionary<string, List<WeakListener>> _listeners = new Dictionary<string, List<WeakListener>>(128);
public static void ClearAllListeners()
{
_listeners.Clear();
}
public static void FlushStaleListeners()
{
foreach (var eventName in _listeners.Keys.ToArray())
{
var eventListeners = _listeners[eventName];
eventListeners.RemoveAll(l => !l.IsAlive);
if (eventListeners.Count == 0)
{
_listeners.Remove(eventName);
}
}
}
public static void Emit(string eventName)
{
var listeners = GetLiveListeners(eventName);
if (listeners != null)
{
foreach (var l in listeners)
{
CallListener(l);
}
}
}
public static void Emit<T>(string eventName, T param0)
{
var listeners = GetLiveListeners(eventName);
if (listeners != null)
{
foreach (var l in listeners)
{
CallListener(l, param0);
}
}
}
public static void Emit<T, U>(string eventName, T param0, U param1)
{
var listeners = GetLiveListeners(eventName);
if (listeners != null)
{
foreach (var l in listeners)
{
CallListener(l, param0, param1);
}
}
}
#region Handler callers with fallback for overloads with less parameters
private static void CallListener<T, U>(WeakListener listener, T param0, U param1)
{
var action = listener.Handler as Action<T, U>;
if (action != null)
{
action(param0, param1);
}
else
{
CallListener(listener, param0);
}
}
private static void CallListener<T>(WeakListener listener, T param0)
{
var action = listener.Handler as Action<T>;
if (action != null)
{
action(param0);
}
else
{
CallListener(listener);
}
}
private static void CallListener(WeakListener listener)
{
var action = listener.Handler as Action;
if (action != null)
{
action();
}
else
{
Log.WarningFormat("Handler for event was of unexpected type. Listener is '{0}'", listener.Listener.Target);
}
}
#endregion
private static List<WeakListener> GetLiveListeners(string eventName)
{
if (!_listeners.ContainsKey(eventName)) return null;
var listeners = _listeners[eventName];
for (var i = listeners.Count - 1; i >= 0; i--)
{
if (!listeners[i].IsAlive)
{
listeners.RemoveAt(i);
Debug.LogFormat("Removing index {0}", i);
}
}
return listeners;
}
public static void Listen(this UnityEngine.Object listener, string eventName, Action handler)
{
AddListener(eventName, listener, handler);
}
public static void Listen<T>(this UnityEngine.Object listener, string eventName, Action<T> handler)
{
AddListener(eventName, listener, handler);
}
public static void Listen<T, U>(this UnityEngine.Object listener, string eventName, Action<T, U> handler)
{
AddListener(eventName, listener, handler);
}
private static void AddListener(string eventName, UnityEngine.Object listener, object handler)
{
if (!_listeners.ContainsKey(eventName))
{
_listeners[eventName] = new List<WeakListener>(16);
};
_listeners[eventName].Add(new WeakListener(listener, handler));
}
public static void StopListening(this UnityEngine.Object listener, string eventName)
{
if (_listeners.ContainsKey(eventName))
{
var listeners = _listeners[eventName];
listeners.RemoveAll(l => l.IsAlive && object.ReferenceEquals(l.Listener.Target, listener));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment