local events = {}
local eventHandleId = 0
local eventHandles = {}
local function AddListener(name, listener)
local listeners = events[name]
if not listeners then
--listeners不再是一个简单的table,通过多个标识符来标识
listeners = { insert = {}, dirty = false, executing = false, destroyed = false }
events[name] = listeners
end
local handleId = listeners[listener] or listeners.insert[listener]
if not handleId then
handleId = eventHandleId + 1
eventHandleId = handleId
--如果在塞入的时候,该listeners正在被触发,则不执行立即塞入的操作,等下一个触发到来的时候执行
if listeners.executing then
listeners.insert[listener] = handleId
listeners.dirty = true
else
listeners[listener] = handleId
end
eventHandles[handleId] = { name, listener }
end
return handleId
end
local function RemoveListener(name, listener, handles)
local listeners = events[name]
if listeners then
if not listener then
for _, handleId in pairs(listeners) do
eventHandles[handleId] = nil
if handles then
handles[handleId] = nil
end
end
--标记其已经destroyed
listeners.destroyed = true
events[name] = nil
else
local handleId = listeners[listener] or listeners.insert[listener]
if handleId then
listeners[listener] = nil
listeners.insert[listener] = nil
eventHandles[handleId] = nil
if handles then
handles[handleId] = nil
end
end
end
end
end
local function RemoveHandle(handleId)
local entry = eventHandles[handleId]
if entry then
RemoveListener(entry[1], entry[2])
end
end
local EventManager = {}
function EventManager.Add(name, listener)
AddListener(name, listener)
end
function EventManager.Remove(name, listener)
RemoveListener(name, listener)
end
function EventManager.Clear()
events = {}
eventHandles = {}
end
function EventManager.Dispatch(name, ...)
local listeners = events[name]
if listeners then
listeners.executing = true
for listener, _ in pairs(listeners) do
if type(listener) == "function" then
listener(name, ...)
end
--可能在执行listener的过程中回调执行了remove,所以需要检测一次是否退出
if listeners.destroyed then
return
end
end
--触发完后,再执行缓存的塞入检测
if listeners.dirty then
for listener, handleId in pairs(listeners.insert) do
listeners[listener] = handleId
listeners.insert[listener] = nil
end
listeners.dirty = false
end
listeners.executing = false
end
end
using System;
using System.Collections.Generic;
public class EventListener
{
public string name;
public Delegate action;
}
public static class EventManger
{
private static Dictionary<string, List<EventListener>> listenList = new Dictionary<string, List<EventListener>>();
private static Dictionary<string, int> listenerStatus = new Dictionary<string, int>();
private static Dictionary<string, List<EventListener>> addList = new Dictionary<string, List<EventListener>>();
private static Dictionary<string, List<EventListener>> removeList = new Dictionary<string, List<EventListener>>();
//查找监听
public static EventListener GetListener(string name, Delegate action)
{
if (action == null) return null;
List<EventListener> listEvent = null;
if (!listenList.TryGetValue(name, out listEvent) || listEvent.Count < 1)
return null;
var ls = listEvent.Find(l => l.action.Method == action.Method);
return ls;
}
//添加事件监听
public static EventListener AddEventListener(string name, Delegate action)
{
if (action == null) return null;
//判断是否已经有
var listener = GetListener(name, action);
if (listener != null)
return listener;
//new 可以用资源池代替
listener = new EventListener();
listener.name = name;
listener.action = action;
//第一次创建,则建立对应的dic
if(!listenList.ContainsKey(name))
{
listenList.Add(name, new List<EventListener>());
addList.Add(name, new List<EventListener>());
removeList.Add(name, new List<EventListener>());
listenerStatus.Add(name, 0);
}
//处于事件触发,则滞后处理
if (listenerStatus[name] > 0)
addList[name].Add(listener);
else
listenList[name].Add(listener);
return listener;
}
//删除事件监听
public static void RemoveListener(string name, EventListener listener)
{
List<EventListener> deleteList = null;
if(listenList.TryGetValue(name, out deleteList))
{
//首先删除addList中的监听
addList[name].Remove(listener);
if(deleteList.Contains(listener))
{
//如果正在触发,则滞后
if (listenerStatus[name] > 0)
removeList[name].Add(listener);
else
{
deleteList.Remove(listener);
//归还到资源池去........
}
}
}
}
//事件触发
public static void DispatchEvent(string name)
{
//...............
List<EventListener> ls = null;
if(listenList.TryGetValue(name, out ls))
{
//标记正在触发
listenerStatus[name]++;
//
foreach(var listener in ls)
{
listener.action.DynamicInvoke(null);
}
var count = listenerStatus[name] - 1;
listenerStatus[name] = count;
//此时执行滞后的增删操作
if(count < 1)
{
var list = addList[name];
ls.AddRange(list);
list.Clear();
list = removeList[name];
foreach (var listener in list)
ls.Remove(listener);
list.Clear();
}
//.......
}
}
}