You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
14 KiB
427 lines
14 KiB
using System; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
|
|
namespace AX.MessageSystem |
|
{ |
|
/// <summary> |
|
/// 消息分发中心。 |
|
/// </summary> |
|
public static class MessageDispatcher |
|
{ |
|
internal class Pair |
|
{ |
|
public string MessageType; |
|
public Action<IMessage> Handler; |
|
|
|
public Pair() { } |
|
public Pair(string messageType, Action<IMessage> handler) |
|
{ |
|
MessageType = messageType; |
|
Handler = handler; |
|
} |
|
} |
|
|
|
internal const float Immediate = 0.0f; |
|
internal const float NextFrame = -1.0f; |
|
|
|
private static Dictionary<string, List<Pair>> filteredHandlers = new Dictionary<string, List<Pair>>(); |
|
private static Dictionary<string, Action<IMessage>> messageHandlers = new Dictionary<string, Action<IMessage>>(); |
|
|
|
private static List<IMessage> messages = new List<IMessage>(); |
|
|
|
public static void Clear() |
|
{ |
|
foreach (var pair in filteredHandlers) |
|
pair.Value.Clear(); |
|
|
|
filteredHandlers.Clear(); |
|
messageHandlers.Clear(); |
|
|
|
messages.Clear(); |
|
} |
|
|
|
public static void AddListener(string messageType, Action<IMessage> handler) |
|
{ |
|
AddListener(messageType, handler, default(string)); |
|
} |
|
|
|
public static void AddListener(string messageType, Action<IMessage> handler, string filter) |
|
{ |
|
if (string.IsNullOrEmpty(messageType) || handler == null) |
|
throw new ArgumentNullException("messageType or handler is not be null."); |
|
|
|
if (string.IsNullOrEmpty(filter)) |
|
{ |
|
if (messageHandlers.ContainsKey(messageType)) |
|
messageHandlers[messageType] += handler; |
|
else |
|
messageHandlers[messageType] = handler; |
|
} |
|
else |
|
{ |
|
List<Pair> handlers = null; |
|
|
|
if (filteredHandlers.TryGetValue(filter, out handlers)) |
|
{ |
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType); |
|
|
|
if (index >= 0) |
|
handlers[index].Handler += handler; |
|
else |
|
handlers.Add(new Pair(messageType, handler)); |
|
} |
|
else |
|
{ |
|
var list = new List<Pair>(); |
|
|
|
list.Add(new Pair(messageType, handler)); |
|
filteredHandlers.Add(filter, list); |
|
} |
|
} |
|
} |
|
|
|
public static void AddListener(string messageType, Action<IMessage> handler, params string[] filters) |
|
{ |
|
if (string.IsNullOrEmpty(messageType) || handler == null) |
|
throw new ArgumentNullException("messageType or handler is not be null."); |
|
|
|
for (var i = 0; i < filters.Length; ++i) |
|
{ |
|
var filter = filters[i]; |
|
|
|
if (string.IsNullOrEmpty(filter)) |
|
{ |
|
if (messageHandlers.ContainsKey(messageType)) |
|
messageHandlers[messageType] += handler; |
|
else |
|
messageHandlers[messageType] = handler; |
|
} |
|
else |
|
{ |
|
List<Pair> handlers = null; |
|
|
|
if (filteredHandlers.TryGetValue(filter, out handlers)) |
|
{ |
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType); |
|
|
|
if (index >= 0) |
|
handlers[index].Handler += handler; |
|
else |
|
handlers.Add(new Pair(messageType, handler)); |
|
} |
|
else |
|
{ |
|
var list = new List<Pair>(); |
|
|
|
list.Add(new Pair(messageType, handler)); |
|
filteredHandlers.Add(filter, list); |
|
} |
|
} |
|
} |
|
} |
|
|
|
public static void RemoveListener(string messageType, Action<IMessage> handler) |
|
{ |
|
RemoveListener(messageType, handler, default(string)); |
|
} |
|
|
|
public static void RemoveListener(string messageType, Action<IMessage> handler, string filter) |
|
{ |
|
if (string.IsNullOrEmpty(messageType) || handler == null) |
|
throw new ArgumentNullException("messageType or handler is not be null."); |
|
|
|
if (string.IsNullOrEmpty(filter)) |
|
{ |
|
if (messageHandlers.ContainsKey(messageType)) |
|
{ |
|
messageHandlers[messageType] -= handler; |
|
|
|
if (messageHandlers[messageType] == null) |
|
messageHandlers.Remove(messageType); |
|
} |
|
} |
|
else |
|
{ |
|
List<Pair> handlers = null; |
|
|
|
if (filteredHandlers.TryGetValue(filter, out handlers)) |
|
{ |
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType); |
|
|
|
if (index >= 0) |
|
{ |
|
handlers[index].Handler -= handler; |
|
|
|
if (handlers[index].Handler == null) |
|
handlers.RemoveAt(index); |
|
} |
|
} |
|
} |
|
} |
|
|
|
public static void RemoveListener(string messageType, Action<IMessage> handler, params string[] filters) |
|
{ |
|
if (string.IsNullOrEmpty(messageType) || handler == null) |
|
throw new ArgumentNullException("messageType or handler is not be null."); |
|
|
|
for (var i = 0; i < filters.Length; ++i) |
|
{ |
|
var filter = filters[i]; |
|
|
|
if (string.IsNullOrEmpty(filter)) |
|
{ |
|
if (messageHandlers.ContainsKey(messageType)) |
|
{ |
|
messageHandlers[messageType] -= handler; |
|
|
|
if (messageHandlers[messageType] == null) |
|
messageHandlers.Remove(messageType); |
|
} |
|
} |
|
else |
|
{ |
|
List<Pair> handlers = null; |
|
|
|
if (filteredHandlers.TryGetValue(filter, out handlers)) |
|
{ |
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType); |
|
|
|
if (index >= 0) |
|
{ |
|
handlers[index].Handler -= handler; |
|
|
|
if (handlers[index].Handler == null) |
|
handlers.RemoveAt(index); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
public static void Update() |
|
{ |
|
//处理延迟消息并决定何时发送它 |
|
for (int i = 0; i < messages.Count; i++) |
|
{ |
|
var message = messages[i]; |
|
|
|
message.Delay -= Time.deltaTime; |
|
|
|
if (message.Delay < 0) |
|
message.Delay = Immediate; |
|
|
|
//是时候发送消息了 |
|
if (!message.IsSent && message.Delay == Immediate) |
|
SendMessage(message); |
|
} |
|
|
|
//回收发送的消息 |
|
for (int i = messages.Count - 1; i >= 0; i--) |
|
{ |
|
var message = messages[i]; |
|
|
|
if (message.IsSent || message.IsHandled) |
|
{ |
|
messages.RemoveAt(i); |
|
|
|
Message.Release((Message)message); |
|
} |
|
} |
|
} |
|
|
|
public static void SendMessage(IMessage message) |
|
{ |
|
if (message == null || string.IsNullOrEmpty(message.Type)) |
|
throw new ArgumentNullException("message"); |
|
|
|
bool missing = true; |
|
|
|
// 处理延迟消息 |
|
if (message.Delay > 0 || message.Delay < 0) |
|
{ |
|
messages.Add(message); |
|
|
|
missing = false; |
|
} |
|
else if (message.Filters == null) |
|
{ |
|
Action<IMessage> action = null; |
|
|
|
if (messageHandlers.TryGetValue(message.Type, out action)) |
|
{ |
|
//触发消息回调 |
|
message.IsSent = true; |
|
action(message); |
|
message.IsHandled = true; |
|
|
|
missing = false; |
|
} |
|
} |
|
else |
|
{ |
|
for (var i = 0; i < message.Filters.Length; ++i) |
|
{ |
|
var filter = message.Filters[i]; |
|
|
|
if (string.IsNullOrEmpty(filter)) |
|
{ |
|
Action<IMessage> action = null; |
|
|
|
if (messageHandlers.TryGetValue(message.Type, out action)) |
|
{ |
|
message.IsSent = true; |
|
action(message); |
|
message.IsHandled = true; |
|
|
|
missing = false; |
|
} |
|
} |
|
else |
|
{ |
|
List<Pair> handlers = null; |
|
|
|
if (filteredHandlers.TryGetValue(filter, out handlers)) |
|
{ |
|
var index = handlers.FindIndex((pair) => pair.MessageType == message.Type); |
|
|
|
if (index >= 0) |
|
{ |
|
message.IsSent = true; |
|
handlers[index].Handler(message); |
|
message.IsHandled = true; |
|
|
|
missing = false; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//如果没有对应的接收方 |
|
if (missing) |
|
{ |
|
if (Application.isEditor) |
|
Debug.LogError("[MessageSystem] 该消息类型 { " + message.Type + " } 没有对应的接收方处理。"); |
|
|
|
message.IsSent = true; |
|
message.IsHandled = true; |
|
} |
|
} |
|
|
|
public static void SendMessage(string type) |
|
{ |
|
SendMessage(null, type, default(object), Immediate, default(string)); |
|
} |
|
|
|
// 注释掉下面方法的原因是开发人员经常使用发送数据的方法 |
|
// 但编译器会定位方法重载到这里 |
|
// 这导致了非必要的排错 |
|
// 如果想要延迟发送,请使用下面更精确的重载方法 |
|
//public static void SendMessage(string type, string filter) |
|
//{ |
|
// SendMessage(null, type, default(object), Immediate, filter); |
|
//} |
|
|
|
// public static void SendMessage(string type, float delay) |
|
// { |
|
// SendMessage(null, type, default(object), delay, default(string)); |
|
// } |
|
|
|
// public static void SendMessage(string type, float delay, string filter) |
|
// { |
|
// SendMessage(null, type, default(object), delay, filter); |
|
// } |
|
|
|
public static void SendMessage(string type, object data) |
|
{ |
|
SendMessage(null, type, data, Immediate, default(string)); |
|
} |
|
|
|
public static void SendMessage(string type, object data, string filter) |
|
{ |
|
SendMessage(null, type, data, Immediate, filter); |
|
} |
|
|
|
public static void SendMessage(string type, object data, float delay) |
|
{ |
|
SendMessage(null, type, data, delay, default(string)); |
|
} |
|
|
|
public static void SendMessage(string type, object data, float delay, string filter) |
|
{ |
|
SendMessage(null, type, data, delay, filter); |
|
} |
|
|
|
public static void SendMessage(object sender, string type) |
|
{ |
|
SendMessage(sender, type, default(object), Immediate, default(string)); |
|
} |
|
|
|
//public static void SendMessage(object sender, string type, float delay) |
|
//{ |
|
// SendMessage(sender, type, default(object), delay, default(string)); |
|
//} |
|
|
|
public static void SendMessage(object sender, string type, string filter) |
|
{ |
|
SendMessage(sender, type, default(object), Immediate, filter); |
|
} |
|
|
|
public static void SendMessage(object sender, string type, float delay, string filter) |
|
{ |
|
SendMessage(sender, type, default(object), delay, filter); |
|
} |
|
|
|
public static void SendMessage(object sender, string type, object data) |
|
{ |
|
SendMessage(sender, type, data, Immediate, default(string)); |
|
} |
|
|
|
public static void SendMessage(object sender, string type, object data, float delay) |
|
{ |
|
SendMessage(sender, type, data, delay, default(string)); |
|
} |
|
|
|
public static void SendMessage(object sender, string type, object data, string filter) |
|
{ |
|
SendMessage(sender, type, data, Immediate, filter); |
|
} |
|
|
|
public static void SendMessage(object sender, string type, object data, float delay, string filter) |
|
{ |
|
var message = Message.Acquire(); |
|
|
|
message.Sender = sender; |
|
message.Type = type; |
|
message.Data = data; |
|
message.Delay = delay; |
|
|
|
if (!string.IsNullOrEmpty(filter)) |
|
message.Filters = new string[] { filter }; |
|
|
|
SendMessage(message); |
|
|
|
if (delay == Immediate) |
|
Message.Release(message); |
|
} |
|
|
|
public static void SendMessage(object sender, string type, object data, float delay, params string[] filters) |
|
{ |
|
var message = Message.Acquire(); |
|
|
|
message.Sender = sender; |
|
message.Type = type; |
|
message.Data = data; |
|
message.Delay = delay; |
|
|
|
if (filters != null) |
|
message.Filters = filters; |
|
|
|
SendMessage(message); |
|
|
|
if (delay == Immediate) |
|
Message.Release(message); |
|
} |
|
} |
|
} |