using Serein.Library; using Serein.Library.Utils; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; namespace Serein.Proto.WebSocket.Handle { /// /// Json消息处理模块 /// public class WebSocketHandleModule { /// /// Json消息处理模块 /// public WebSocketHandleModule(WebSocketHandleModuleConfig config) { moduleConfig = config; } /// /// 模块的处理配置 /// private readonly WebSocketHandleModuleConfig moduleConfig; /// /// 用来判断消息是否重复 /// private HashSet _myMsgIdHash = new HashSet(); /// /// 存储处理数据的配置 /// public ConcurrentDictionary MyHandleConfigs = new ConcurrentDictionary(); /// /// 添加处理配置 /// /// 处理模块 internal bool AddHandleConfigs(WebSocketHandleConfiguration config) { if (!MyHandleConfigs.ContainsKey(config.ThemeValue)) { MyHandleConfigs[config.ThemeValue] = config; return true; } else { return false; } } /// /// 移除某个处理模块 /// /// /// public bool RemoveConfig(ISocketHandleModule socketControlBase) { foreach (var kv in MyHandleConfigs.ToArray()) { var config = kv.Value; MyHandleConfigs.TryRemove(kv.Key, out _); } return MyHandleConfigs.Count == 0; } /// /// 卸载当前模块的所有配置 /// public void UnloadConfig() { var temp = MyHandleConfigs.Values; MyHandleConfigs.Clear(); } /// /// 处理JSON数据 /// public async Task HandleAsync(WebSocketMsgContext context) { var jsonObject = context.MsgRequest; // 获取到消息 string theme = jsonObject.GetValue(moduleConfig.ThemeJsonKey)?.ToString(); if (!MyHandleConfigs.TryGetValue(theme, out var handldConfig)) { return; // 没有主题 } context.MsgTheme = theme; // 添加主题 string msgId = jsonObject.GetValue(moduleConfig.MsgIdJsonKey)?.ToString(); if (_myMsgIdHash.Contains(msgId)) { SereinEnv.WriteLine(InfoType.WARN, $"[{msgId}]{theme} 消息重复"); return; } context.MsgId = msgId; // 添加 ID _myMsgIdHash.Add(msgId); try { var dataObj = jsonObject.GetValue(moduleConfig.DataJsonKey); context.MsgData = dataObj; // 添加消息 if (TryGetParameters(handldConfig, context, out var args)) { var result = await HandleAsync(handldConfig, args); if (handldConfig.IsReturnValue) { await context.RepliedAsync(moduleConfig, context, result); } } } catch (Exception ex) { SereinEnv.WriteLine(InfoType.ERROR, $"error in ws : {ex.Message}{Environment.NewLine}json value:{jsonObject}"); } finally { context.Handle = true; } } /// /// 调用 /// /// /// /// public static async Task HandleAsync(HandleConfiguration config, object[] args) { var instance = config.InstanceFactory.Invoke(); var result = await config.DelegateDetails.InvokeAsync(instance, args); return result; } /// /// 获取入参参数 /// /// 处理配置 /// 处理上下文 /// 返回的入参参数 /// internal static bool TryGetParameters(HandleConfiguration config, WebSocketMsgContext context, out object[] args) { args = new object[config.ParameterType.Length]; bool isCanInvoke = true; ; // 表示是否可以调用方法 for (int i = 0; i < config.ParameterType.Length; i++) { var type = config.ParameterType[i]; // 入参变量类型 var argName = config.ParameterName[i]; // 入参参数名称 #region 传递消息ID if (config.UseMsgId[i]) { args[i] = context.MsgId; } #endregion #region DATA JSON数据 else if (config.UseRequest[i]) { args[i] = context.MsgRequest.ToObject(type); } #endregion #region DATA JSON数据 else if (config.UseData[i]) { args[i] = context.MsgData.ToObject(type); } #endregion #region 值类型参数 else if (type.IsValueType) { var jsonValue = context.MsgData.GetValue(argName); if (!(jsonValue is null)) { args[i] = jsonValue.ToObject(type); } else { if (config.ArgNotNull && !config.IsCheckArgNotNull[i]) // 检查不能为空 { args[i] = Activator.CreateInstance(type); // 值类型返回默认值 } else { isCanInvoke = false; // 参数不能为空,终止调用 break; } } } #endregion #region 引用类型参数 else if (type.IsClass) { var jsonValue = context.MsgData.GetValue(argName); if (!(jsonValue is null)) { args[i] = jsonValue.ToObject(type); } else { if (config.ArgNotNull && !config.IsCheckArgNotNull[i]) { args[i] = null; // 引用类型返回null } else { isCanInvoke = false; // 参数不能为空,终止调用 break; } } } #endregion #region 传递消息委托 else if (type.IsGenericType) // 传递SendAsync委托 { if (type.IsAssignableFrom(typeof(Func))) { args[i] = new Func(async data => { var jsonText = JsonHelper.Serialize(data); await context.SendAsync(jsonText); }); } else if (type.IsAssignableFrom(typeof(Func))) { args[i] = new Func(async data => { await context.SendAsync(data); }); } else if (type.IsAssignableFrom(typeof(Action))) { args[i] = new Action(async data => { var jsonText = JsonHelper.Serialize(data); await context.SendAsync(jsonText); }); } else if (type.IsAssignableFrom(typeof(Action))) { args[i] = new Action(async data => { var jsonText = JsonHelper.Serialize(data); await context.SendAsync(jsonText); }); } } #endregion } return isCanInvoke; } } }