声明:
轻量级和高效的事件分发管理类。
您可以通过监听事件,而不必担心重复监听的可能性。
还可以使用对象删除所有相关的侦听器。
注意:
两种方式选其一即可
第一种 object字典实现 可以 通过 off( caller ) 的方式 移除自身所有监听事件
第二种 由模板实现
第一种方式:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
/**
*
* class: GlobalEventCenter
* Listen&Dispatch Event for global-environment
*
* Declaration:
* Lightweight and efficient event distribution management class.
* You can listen for events via on and do not need to worry about the possibility of repeated listener.
* You can also use objects to remove all related listener.
*
* Function:
* On: Add Event Handler
* Off: Remove Event Handler
* Event: Dispatch Event
*
*
* Anchor: ChenJC
* Time: 2022/10/09
* Source: https://blog.csdn.net/qq_39162566/article/details/113106880
*
*/
public class GlobalEventCenter
{
//protected class EventHandler
//{
// public object caller;
// public Action func;
// public static EventHandler Create( Action func, object caller = null )
// {
// EventHandler handler = new EventHandler();
// handler.caller = caller;
// handler.func = func;
// return handler;
// }
//}
//protected class ArgEventHandler
//{
// public object caller;
// public Action<object> func;
// public static ArgEventHandler Create( Action<object> func, object caller = null )
// {
// ArgEventHandler handler = new ArgEventHandler();
// handler.caller = caller;
// handler.func = func;
// return handler;
// }
//}
private static Dictionary<string, List<Delegate>> eventPool = new Dictionary<string, List<Delegate>>();
private static HashSet<Delegate> once = new HashSet<Delegate>();
//private static Dictionary<string, List<Action<object>>> hasArgEventDict = new Dictionary<string, List<Action<object>>>();
#region Add Event Listener Methods
// public static void On( string eventID, Action func, object caller = null )
// {
// if ( !Has( eventID, func, caller ) )
// {
// List<EventHandler> result = null;
// if ( voidArgEventDict.TryGetValue( eventID, out result ) )
// {
// result.Add( EventHandler.Create( func, caller ) );
// }
// else
// {
// voidArgEventDict.Add( eventID, new List<EventHandler>() { EventHandler.Create( func, caller ) } );
// }
// }
//#if UNITY_EDITOR
// else
// {
// Debug.Log( $"<color=#ff0000>----------- Listener Has already exist: {eventID},{caller.ToString()},{func.ToString()}</color>" );
// }
//#endif
// }
//public static void On( string eventID, Action func )
//{
// Action handler = null;
// if ( !voidArgEventDict.TryGetValue( eventID, out handler ) )
// {
// voidArgEventDict.Add( eventID, func );
// }
// else
// {
// handler -= func;
// handler += func;
// }
//}
// public static void On( string eventID, Action<object> func, object caller = null )
// {
// if ( !Has( eventID, func, caller ) )
// {
// List<ArgEventHandler> result = null;
// if ( hasArgEventDict.TryGetValue( eventID, out result ) )
// {
// result.Add( ArgEventHandler.Create( func, caller ) );
// }
// else
// {
// hasArgEventDict.Add( eventID, new List<ArgEventHandler>() { ArgEventHandler.Create( func, caller ) } );
// }
// }
//#if UNITY_EDITOR
// else
// {
// Debug.Log( $"<color=#ff0000>----------- Listener Has already exist: {eventID},{caller.ToString()},{func.ToString()}</color>" );
// }
//#endif
// }
public static void On( string eventID, Action func )
{
if ( !Has( eventID, func ) )
{
List<Delegate> result = null;
if ( eventPool.TryGetValue( eventID, out result ) )
{
result.Add( func );
}
else
{
eventPool.Add( eventID, new List<Delegate>() { func } );
}
}
#if UNITY_EDITOR
else
{
Debug.Log( $"<color=#ff0000>----------- Listener Has already exist: {eventID},{func.ToString()}</color>" );
}
#endif
}
public static void On( string eventID, Action<object> func )
{
if ( !Has( eventID, func ) )
{
List<Delegate> result = null;
if ( eventPool.TryGetValue( eventID, out result ) )
{
result.Add( func );
}
else
{
eventPool.Add( eventID, new List<Delegate>() { func } );
}
}
#if UNITY_EDITOR
else
{
Debug.Log( $"<color=#ff0000>----------- Listener Has already exist: {eventID},{func.ToString()}</color>" );
}
#endif
}
public static void On( string eventID, Action<object, object> func )
{
if ( !Has( eventID, func ) )
{
List<Delegate> result = null;
if ( eventPool.TryGetValue( eventID, out result ) )
{
result.Add( func );
}
else
{
eventPool.Add( eventID, new List<Delegate>() { func } );
}
}
#if UNITY_EDITOR
else
{
Debug.Log( $"<color=#ff0000>----------- Listener Has already exist: {eventID},{func.ToString()}</color>" );
}
#endif
}
public static void On( string eventID, Action<object, object, object> func )
{
if ( !Has( eventID, func ) )
{
List<Delegate> result = null;
if ( eventPool.TryGetValue( eventID, out result ) )
{
result.Add( func );
}
else
{
eventPool.Add( eventID, new List<Delegate>() { func } );
}
}
#if UNITY_EDITOR
else
{
Debug.Log( $"<color=#ff0000>----------- Listener Has already exist: {eventID},{func.ToString()}</color>" );
}
#endif
}
public static void Once( string eventID, Action func )
{
once.Add( func );
On( eventID, func );
}
public static void Once( string eventID, Action<object> func )
{
once.Add( func );
On( eventID, func );
}
public static void Once( string eventID, Action<object, object> func )
{
once.Add( func );
On( eventID, func );
}
public static void Once( string eventID, Action<object, object, object> func )
{
once.Add( func );
On( eventID, func );
}
#endregion
#region Find Methods
/// <summary>
///
/// declara:
/// find method by methodInfo and caller
///
/// Example:
/// var _delegate = Find( eventID, func.Method, func.Target );
///
/// </summary>
/// <param name="eventID"></param>
/// <param name="method"></param>
/// <param name="target"></param>
/// <returns></returns>
public static Delegate Find( string eventID, MethodInfo method, object target )
{
List<Delegate> handlers = null;
if ( eventPool.TryGetValue( eventID, out handlers ) )
{
return handlers.Find( handler => { return handler.Method == method && handler.Target == target; } );
}
return null;
}
#endregion
#region Check Methods
/// <summary>
/// Check Listener Has already exist
/// </summary>
/// <param name="eventID"></param>
/// <param name="func"></param>
/// <param name="caller"></param>
/// <returns></returns>
//public static bool Has( string eventID, Action func, object caller = null )
//{
// List<EventHandler> result = null;
// //if ( voidArgEventDict.TryGetValue( eventID, out result ) )
// //{
// // for ( int i = 0; i < result.Count; i++ )
// // {
// // if ( result[ i ].caller == caller && result[ i ].func == func )
// // {
// // return true;
// // }
// // }
// //}
// return false;
//}
public static bool Has( string eventID, Action func )
{
//List<Delegate> handlers = null;
//if ( eventPool.TryGetValue( eventID, out handlers ) )
//{
// return handlers.Find( handler => { return handler.Method == func.Method && handler.Target == func.Target; } ) != null;
//}
//return false;
return Find( eventID, func.Method, func.Target ) != null;
}
public static bool Has( string eventID, Action<object> func )
{
//List<Delegate> handlers = null;
//if ( eventPool.TryGetValue( eventID, out handlers ) )
//{
// return handlers.Find( handler => { return handler.Method == func.Method && handler.Target == func.Target; } ) != null;
//}
//return false;
return Find( eventID, func.Method, func.Target ) != null;
}
public static bool Has( string eventID, Action<object, object> func )
{
//List<Delegate> handlers = null;
//if ( eventPool.TryGetValue( eventID, out handlers ) )
//{
// return handlers.Find( handler => { return handler.Method == func.Method && handler.Target == func.Target; } ) != null;
//}
//return false;
return Find( eventID, func.Method, func.Target ) != null;
}
public static bool Has( string eventID, Action<object, object, object> func )
{
//List<Delegate> handlers = null;
//if ( eventPool.TryGetValue( eventID, out handlers ) )
//{
// return handlers.Find( handler => { return handler.Method == func.Method && handler.Target == func.Target; } ) != null;
//}
return Find( eventID, func.Method, func.Target ) != null;
}
/// <summary>
/// Check Listener Has already exist
/// </summary>
/// <param name="eventID"></param>
/// <param name="func"></param>
/// <param name="caller"></param>
/// <returns></returns>
//public static bool Has( string eventID, Action<object> func, object caller = null )
//{
// //List<ArgEventHandler> result = null;
// //if ( hasArgEventDict.TryGetValue( eventID, out result ) )
// //{
// // for ( int i = 0; i < result.Count; i++ )
// // {
// // if ( result[ i ].caller == caller && result[ i ].func == func )
// // {
// // return true;
// // }
// // }
// //}
// return false;
//}
//public static bool Has( string eventID, Action<object> func )
//{
// List<Action<object>> handlers = null;
// if ( hasArgEventDict.TryGetValue( eventID, out handlers ) )
// {
// return handlers.Find( handler => { return handler == func; } ) != null;
// }
// return false;
//}
#endregion
#region Remove Event Listener Methods
public static void Off()
{
eventPool.Clear();
}
public static void Off( string eventID )
{
eventPool.Remove( eventID );
}
public static void Off( object caller )
{
foreach ( var pair in eventPool )
{
for ( int i = 0; i < pair.Value.Count; i++ )
{
if ( pair.Value[ i ].Target == caller )
{
pair.Value.RemoveAt( i-- );
}
}
}
//foreach ( var pair in voidArgEventDict )
//{
// for ( int i = 0; i < pair.Value.Count; i++ )
// {
// if ( pair.Value[ i ].caller == caller )
// {
// pair.Value.RemoveAt( i-- );
// }
// }
//}
//foreach ( var pair in hasArgEventDict )
//{
// for ( int i = 0; i < pair.Value.Count; i++ )
// {
// if ( pair.Value[ i ].caller == caller )
// {
// pair.Value.RemoveAt( i-- );
// }
// }
//}
}
public static void Off( string eventID, Action func )
{
List<Delegate> result = null;
if ( eventPool.TryGetValue( eventID, out result ) )
{
int index = result.FindIndex( handler => { return handler.Equals( func ); } );
if ( -1 != index )
{
result.RemoveAt( index );
}
}
//List<EventHandler> handlers = null;
//if ( voidArgEventDict.TryGetValue( eventID, out handlers ) )
//{
// for ( int i = 0; i < handlers.Count; i++ )
// {
// if ( handlers[ i ].caller == caller && handlers[ i ].func == func )
// {
// handlers.RemoveAt( i-- );
// }
// }
//}
}
//public static void Off( string eventID, Action<object> func, object caller = null )
//{
// //List<ArgEventHandler> handlers = null;
// //if ( hasArgEventDict.TryGetValue( eventID, out handlers ) )
// //{
// // for ( int i = 0; i < handlers.Count; i++ )
// // {
// // if ( handlers[ i ].caller == caller && handlers[ i ].func == func )
// // {
// // handlers.RemoveAt( i-- );
// // }
// // }
// //}
//}
#endregion
#region dispath event methods
public static void Event( string eventID )
{
List<Delegate> handlers = null;
if ( eventPool.TryGetValue( eventID, out handlers ) )
{
Delegate handler = null;
for ( int i = 0; i < handlers.Count; i++ )
{
handler = handlers[ i ];
Action func = handler as Action;
func?.Invoke();
if ( once.Contains( func ) )
{
handlers.RemoveAt( i-- );
}
}
}
}
//if ( voidArgEventDict.TryGetValue( eventID, out handlers ) )
//{
// for ( int i = 0; i < handlers.Count; i++ )
// {
// handlers[ i ].func?.Invoke();
// }
//}
public static void Event( string eventID, object arg )
{
//List<ArgEventHandler> handlers = null;
//if ( hasArgEventDict.TryGetValue( eventID, out handlers ) )
//{
// for ( int i = 0; i < handlers.Count; i++ )
// {
// handlers[ i ].func?.Invoke( arg );
// }
//}
List<Delegate> handlers = null;
if ( eventPool.TryGetValue( eventID, out handlers ) )
{
Delegate handler = null;
for ( int i = 0; i < handlers.Count; i++ )
{
handler = handlers[ i ];
Action<object> func = handler as Action<object>;
func?.Invoke( arg );
if ( once.Contains( func ) )
{
handlers.RemoveAt( i-- );
}
}
//foreach ( var handler in handlers )
//{
// Action<object> func = handler as Action<object>;
// func?.Invoke( arg );
//#if UNITY_EDITOR || UNITY_EDITOR_WIN || UNITY_2019_4_OR_NEWER || UNITY_ANDROID
// /**
// * When the conversion fails
// * Overloaded methods are compatible when called with arguments
// *
// */
// if ( null == func )
// {
// Action pFunc = handler as Action;
// if ( null != pFunc && null != pFunc.Target )
// {
// Type type = pFunc.Target.GetType();
// MethodInfo method = type.GetMethod( pFunc.Method.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, new Type[] { typeof( object ) }, null );
// object[] args = new object[] { arg };
// method?.Invoke( pFunc.Target, new object[] { arg } );
// }
// }
//#endif
//}
}
}
public static void Event( string eventID, object arg1, object arg2 )
{
//List<ArgEventHandler> handlers = null;
//if ( hasArgEventDict.TryGetValue( eventID, out handlers ) )
//{
// for ( int i = 0; i < handlers.Count; i++ )
// {
// handlers[ i ].func?.Invoke( arg );
// }
//}
//List<Delegate> handlers = null;
//if ( eventPool.TryGetValue( eventID, out handlers ) )
//{
// foreach ( var handler in handlers )
// {
// Action<object, object> func = handler as Action<object, object>;
// func?.Invoke( arg1, arg2 );
// }
//}
List<Delegate> handlers = null;
if ( eventPool.TryGetValue( eventID, out handlers ) )
{
Delegate handler = null;
for ( int i = 0; i < handlers.Count; i++ )
{
handler = handlers[ i ];
Action<object, object> func = handler as Action<object, object>;
func?.Invoke( arg1, arg2 );
if ( once.Contains( func ) )
{
handlers.RemoveAt( i-- );
}
}
}
}
public static void Event( string eventID, object arg1, object arg2, object arg3 )
{
//List<ArgEventHandler> handlers = null;
//if ( hasArgEventDict.TryGetValue( eventID, out handlers ) )
//{
// for ( int i = 0; i < handlers.Count; i++ )
// {
// handlers[ i ].func?.Invoke( arg );
// }
//}
//List<Delegate> handlers = null;
//if ( eventPool.TryGetValue( eventID, out handlers ) )
//{
// foreach ( var handler in handlers )
// {
// Action<object, object, object> func = handler as Action<object, object, object>;
// func?.Invoke( arg1, arg2, arg3 );
// }
//}
List<Delegate> handlers = null;
if ( eventPool.TryGetValue( eventID, out handlers ) )
{
Delegate handler = null;
for ( int i = 0; i < handlers.Count; i++ )
{
handler = handlers[ i ];
Action<object, object, object> func = handler as Action<object, object, object>;
func?.Invoke( arg1, arg2, arg3 );
if ( once.Contains( func ) )
{
handlers.RemoveAt( i-- );
}
}
}
}
#endregion
}
第二种:
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public delegate void EventCallBack();
public delegate void EventCallBack<T>(T arg1);
public delegate void EventCallBack<T, W>(T arg1, W arg2);
public delegate void EventCallBack<T, W, E>(T arg1, W arg2, E arg3);
public delegate void EventCallBack<T, W, E, R>(T arg1, W arg2, E arg3, R arg4);
public delegate void EventCallBack<T, W, E, R, Y>(T arg1, W arg2, E arg3, R arg4, Y arg5);
public class Watcher
{
private static Dictionary<string, Delegate> m_EventTable = new Dictionary<string, Delegate>();
static void TryAddListen(string eventType, Delegate callBack)
{
if (!m_EventTable.ContainsKey(eventType))
{
m_EventTable.Add(eventType, null);
}
Delegate d = m_EventTable[eventType];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试为事件{0}添加不同类型的委托,当前事件所对应的委托是{1},要添加的委托是{2}", eventType, d.GetType(), callBack.GetType()));
}
}
static void TryRemoveListen(string eventType, Delegate callBack)
{
if (m_EventTable.ContainsKey(eventType))
{
Delegate d = m_EventTable[eventType];
if (d == null)
{
throw new Exception(string.Format("移除监听错误:事件{0}没有对应的委托", eventType));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除监听错误:尝试为事件{0}移除不同的类型的委托,当前委托类型为{1},要移除的对象为{2}", eventType, d, callBack));
}
}
else
{
throw new Exception(string.Format("移除监听错误:没有事件码{0}", eventType));
}
}
static void OnListenRemove(string eventType)
{
if (m_EventTable[eventType] == null)
{
m_EventTable.Remove(eventType);
}
}
public static void On(string eventType, EventCallBack callback)
{
TryAddListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack)m_EventTable[eventType] + callback;
}
public static void On<T>(string eventType, EventCallBack<T> callback)
{
TryAddListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack<T>)m_EventTable[eventType] + callback;
}
public static void On<T, W>(string eventType, EventCallBack<T, W> callback)
{
TryAddListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack<T, W>)m_EventTable[eventType] + callback;
}
public static void On<T, W, E>(string eventType, EventCallBack<T, W, E> callback)
{
TryAddListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack<T, W, E>)m_EventTable[eventType] + callback;
}
public static void On<T, W, E, R>(string eventType, EventCallBack<T, W, E, R> callback)
{
TryAddListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack<T, W, E, R>)m_EventTable[eventType] + callback;
}
public static void On<T, W, E, R, Y>(string eventType, EventCallBack<T, W, E, R, Y> callback)
{
TryAddListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack<T, W, E, R, Y>)m_EventTable[eventType] + callback;
}
public static void Off(string eventType, EventCallBack callback = null)
{
TryRemoveListen(eventType, callback);
m_EventTable[eventType] = (EventCallBack)m_EventTable[eventType] - callback;
OnListenRemove(eventType);
}
public static void Off<T>(string eventType, EventCallBack<T> callBack)
{
TryRemoveListen(eventType, callBack);
m_EventTable[eventType] = (EventCallBack<T>)m_EventTable[eventType] - callBack;
OnListenRemove(eventType);
}
public static void Off<T, W>(string eventType, EventCallBack<T, W> callBack)
{
TryRemoveListen(eventType, callBack);
m_EventTable[eventType] = (EventCallBack<T, W>)m_EventTable[eventType] - callBack;
OnListenRemove(eventType);
}
public static void Off<T, W, E>(string eventType, EventCallBack<T, W, E> callBack)
{
TryRemoveListen(eventType, callBack);
m_EventTable[eventType] = (EventCallBack<T, W, E>)m_EventTable[eventType] - callBack;
OnListenRemove(eventType);
}
public static void Off<T, W, E, R>(string eventType, EventCallBack<T, W, E, R> callBack)
{
TryRemoveListen(eventType, callBack);
m_EventTable[eventType] = (EventCallBack<T, W, E, R>)m_EventTable[eventType] - callBack;
OnListenRemove(eventType);
}
public static void Off<T, W, E, R, Y>(string eventType, EventCallBack<T, W, E, R, Y> callBack)
{
TryRemoveListen(eventType, callBack);
m_EventTable[eventType] = (EventCallBack<T, W, E, R, Y>)m_EventTable[eventType] - callBack;
OnListenRemove(eventType);
}
public static void Dispatch(string eventType)
{
Delegate d;
if (m_EventTable.TryGetValue(eventType, out d))
{
EventCallBack callBack = d as EventCallBack;
if (callBack != null)
{
callBack();
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}对应委托具有不同的类型", eventType));
}
}
}
public static void Dispatch<T>(string eventType, T arg)
{
Delegate d;
if (m_EventTable.TryGetValue(eventType, out d))
{
EventCallBack<T> callBack = d as EventCallBack<T>;
if (callBack != null)
{
callBack(arg);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}对应委托具有不同的类型", eventType));
}
}
}
public static void Dispatch<T, W>(string eventType, T arg1, W arg2)
{
Delegate d;
if (m_EventTable.TryGetValue(eventType, out d))
{
EventCallBack<T, W> callBack = d as EventCallBack<T, W>;
if (callBack != null)
{
callBack(arg1, arg2);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}对应委托具有不同的类型", eventType));
}
}
}
public static void Dispatch<T, W, E>(string eventType, T arg1, W arg2, E arg3)
{
Delegate d;
if (m_EventTable.TryGetValue(eventType, out d))
{
EventCallBack<T, W, E> callBack = d as EventCallBack<T, W, E>;
if (callBack != null)
{
callBack(arg1, arg2, arg3);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}对应委托具有不同的类型", eventType));
}
}
}
public static void Dispatch<T, W, E, R>(string eventType, T arg1, W arg2, E arg3, R arg4)
{
Delegate d;
if (m_EventTable.TryGetValue(eventType, out d))
{
EventCallBack<T, W, E, R> callBack = d as EventCallBack<T, W, E, R>;
if (callBack != null)
{
callBack(arg1, arg2, arg3, arg4);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}对应委托具有不同的类型", eventType));
}
}
}
public static void Dispatch<T, W, E, R, Y>(string eventType, T arg1, W arg2, E arg3, R arg4, Y arg5)
{
Delegate d;
if (m_EventTable.TryGetValue(eventType, out d))
{
EventCallBack<T, W, E, R, Y> callBack = d as EventCallBack<T, W, E, R, Y>;
if (callBack != null)
{
callBack(arg1, arg2, arg3, arg4, arg5);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}对应委托具有不同的类型", eventType));
}
}
}
}