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.
269 lines
9.3 KiB
269 lines
9.3 KiB
//------------------------------------------------------------------------------ |
|
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 |
|
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 |
|
// CSDN博客:https://blog.csdn.net/qq_40374647 |
|
// 哔哩哔哩视频:https://space.bilibili.com/94253567 |
|
// Gitee源代码仓库:https://gitee.com/RRQM_Home |
|
// Github源代码仓库:https://github.com/RRQM |
|
// API首页:https://www.yuque.com/rrqm/touchsocket/index |
|
// 交流QQ群:234762506 |
|
// 感谢您的下载和使用 |
|
//------------------------------------------------------------------------------ |
|
//------------------------------------------------------------------------------ |
|
|
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Threading; |
|
using System.Threading.Tasks; |
|
using TouchSocket.Resources; |
|
|
|
namespace TouchSocket.Core |
|
{ |
|
/// <summary> |
|
/// 消息通知类。内部全为弱引用。 |
|
/// </summary> |
|
public class AppMessenger |
|
{ |
|
private static AppMessenger m_instance; |
|
private readonly ReaderWriterLockSlim m_lockSlim = new ReaderWriterLockSlim(); |
|
private readonly Dictionary<string, List<MessageInstance>> m_tokenAndInstance = new Dictionary<string, List<MessageInstance>>(); |
|
|
|
/// <summary> |
|
/// 默认单例实例 |
|
/// </summary> |
|
public static AppMessenger Default |
|
{ |
|
get |
|
{ |
|
if (m_instance != null) |
|
{ |
|
return m_instance; |
|
} |
|
lock (typeof(AppMessenger)) |
|
{ |
|
if (m_instance != null) |
|
{ |
|
return m_instance; |
|
} |
|
m_instance = new AppMessenger(); |
|
return m_instance; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 允许多广播注册 |
|
/// </summary> |
|
public bool AllowMultiple { get; set; } |
|
|
|
/// <summary> |
|
/// 添加 |
|
/// </summary> |
|
/// <param name="token"></param> |
|
/// <param name="messageInstance"></param> |
|
/// <exception cref="MessageRegisteredException"></exception> |
|
public void Add(string token, MessageInstance messageInstance) |
|
{ |
|
using (WriteLock writeLock = new WriteLock(m_lockSlim)) |
|
{ |
|
if (m_tokenAndInstance.ContainsKey(token)) |
|
{ |
|
if (!AllowMultiple) |
|
{ |
|
throw new MessageRegisteredException(TouchSocketStatus.TokenExisted.GetDescription(token)); |
|
} |
|
m_tokenAndInstance[token].Add(messageInstance); |
|
} |
|
else |
|
{ |
|
m_tokenAndInstance.Add(token, new List<MessageInstance>() |
|
{ |
|
messageInstance |
|
}); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 判断能否触发该消息,意味着该消息是否已经注册。 |
|
/// </summary> |
|
/// <param name="token"></param> |
|
/// <returns></returns> |
|
public bool CanSendMessage(string token) |
|
{ |
|
using (ReadLock readLock = new ReadLock(m_lockSlim)) |
|
{ |
|
return m_tokenAndInstance.ContainsKey(token); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 清除所有消息 |
|
/// </summary> |
|
public void Clear() |
|
{ |
|
using (WriteLock writeLock = new WriteLock(m_lockSlim)) |
|
{ |
|
m_tokenAndInstance.Clear(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 获取所有消息 |
|
/// </summary> |
|
/// <returns></returns> |
|
public string[] GetAllMessage() |
|
{ |
|
using (ReadLock readLock = new ReadLock(m_lockSlim)) |
|
{ |
|
return m_tokenAndInstance.Keys.ToArray(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 移除 |
|
/// </summary> |
|
/// <param name="token"></param> |
|
public void Remove(string token) |
|
{ |
|
using (WriteLock writeLock = new WriteLock(m_lockSlim)) |
|
{ |
|
m_tokenAndInstance.Remove(token); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 按对象移除 |
|
/// </summary> |
|
/// <param name="messageObject"></param> |
|
public void Remove(IMessageObject messageObject) |
|
{ |
|
using (WriteLock writeLock = new WriteLock(m_lockSlim)) |
|
{ |
|
List<string> key = new List<string>(); |
|
|
|
foreach (var item in m_tokenAndInstance.Keys) |
|
{ |
|
foreach (var item2 in m_tokenAndInstance[item].ToArray()) |
|
{ |
|
if (messageObject == item2.MessageObject) |
|
{ |
|
m_tokenAndInstance[item].Remove(item2); |
|
if (m_tokenAndInstance[item].Count == 0) |
|
{ |
|
key.Add(item); |
|
} |
|
} |
|
} |
|
} |
|
|
|
foreach (var item in key) |
|
{ |
|
m_tokenAndInstance.Remove(item); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 发送消息 |
|
/// </summary> |
|
/// <param name="token"></param> |
|
/// <param name="parameters"></param> |
|
/// <exception cref="MessageNotFoundException"></exception> |
|
public Task SendAsync(string token, params object[] parameters) |
|
{ |
|
return EasyTask.Run(() => |
|
{ |
|
using (ReadLock readLock = new ReadLock(m_lockSlim)) |
|
{ |
|
if (m_tokenAndInstance.TryGetValue(token, out List<MessageInstance> list)) |
|
{ |
|
List<MessageInstance> clear = new List<MessageInstance>(); |
|
|
|
foreach (var item in list) |
|
{ |
|
if (!item.Static && !item.WeakReference.TryGetTarget(out _)) |
|
{ |
|
clear.Add(item); |
|
continue; |
|
} |
|
try |
|
{ |
|
item.Invoke(item.MessageObject, parameters); |
|
} |
|
catch |
|
{ |
|
} |
|
} |
|
|
|
foreach (var item in clear) |
|
{ |
|
list.Remove(item); |
|
} |
|
} |
|
else |
|
{ |
|
throw new MessageNotFoundException(TouchSocketStatus.MessageNotFound.GetDescription(token)); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
/// <summary> |
|
/// 发送消息,当多播时,只返回最后一个返回值 |
|
/// </summary> |
|
/// <typeparam name="T">返回值类型</typeparam> |
|
/// <param name="token"></param> |
|
/// <param name="parameters"></param> |
|
/// <returns></returns> |
|
/// <exception cref="MessageNotFoundException"></exception> |
|
public Task<T> SendAsync<T>(string token, params object[] parameters) |
|
{ |
|
return EasyTask.Run(() => |
|
{ |
|
using (ReadLock readLock = new ReadLock(m_lockSlim)) |
|
{ |
|
if (m_tokenAndInstance.TryGetValue(token, out List<MessageInstance> list)) |
|
{ |
|
T result = default; |
|
List<MessageInstance> clear = new List<MessageInstance>(); |
|
for (int i = 0; i < list.Count; i++) |
|
{ |
|
var item = list[i]; |
|
if (!item.Static && !item.WeakReference.TryGetTarget(out _)) |
|
{ |
|
clear.Add(item); |
|
continue; |
|
} |
|
|
|
try |
|
{ |
|
if (i == list.Count - 1) |
|
{ |
|
result = (T)item.Invoke(item.MessageObject, parameters); |
|
} |
|
else |
|
{ |
|
item.Invoke(item.MessageObject, parameters); |
|
} |
|
} |
|
catch |
|
{ |
|
} |
|
} |
|
|
|
foreach (var item in clear) |
|
{ |
|
list.Remove(item); |
|
} |
|
return result; |
|
} |
|
else |
|
{ |
|
throw new MessageNotFoundException(TouchSocketStatus.MessageNotFound.GetDescription(token)); |
|
} |
|
} |
|
}); |
|
} |
|
} |
|
} |