using System.Diagnostics; using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization; namespace OMS.NET.Instructs { /// /// 声明json转换的命名策略 /// class InstructNamingPolicy : JsonNamingPolicy { public override string ConvertName(string name) { return Convert(name); } public static string Convert(string name) => name switch { "Type" => "type", "Class" => "class", "Conveyor" => "conveyor", "Time" => "time", "Data" => "data", _ => name, }; } /// /// 实现依据type和class的值决定反序列化的对象类型 /// class InstructConverter : JsonConverter { public override Instruct Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); JsonElement root = doc.RootElement; //Console.WriteLine(root.GetRawText()); if (root.TryGetProperty("type", out JsonElement typeProperty)) { string? typeValue = typeProperty.GetString(); string? classValue = root.TryGetProperty("class", out JsonElement classProperty) ? classProperty.GetString() : null; Instruct? instruct = typeValue switch { //实现新指令需在这里添加反序列化类型,限定为客户端发过来的指令类型 "get_publickey" => JsonSerializer.Deserialize(root.GetRawText(), options), "get_serverImg" => JsonSerializer.Deserialize(root.GetRawText(), options), "get_serverConfig" => JsonSerializer.Deserialize(root.GetRawText(), options), "login" => JsonSerializer.Deserialize(root.GetRawText(), options), "test" => JsonSerializer.Deserialize(root.GetRawText(), options), "get_userData" => JsonSerializer.Deserialize(root.GetRawText(), options), "get_presence" => JsonSerializer.Deserialize(root.GetRawText(), options), "get_mapData" => JsonSerializer.Deserialize(root.GetRawText(), options), "get_mapLayer" => JsonSerializer.Deserialize(root.GetRawText(), options), "ping" => JsonSerializer.Deserialize(root.GetRawText(), options), //广播指令 "broadcast" => classValue switch { //广播指令继承结构 "point" => JsonSerializer.Deserialize(root.GetRawText(), options), "line" => JsonSerializer.Deserialize(root.GetRawText(), options), "area" => JsonSerializer.Deserialize(root.GetRawText(), options), "curve" => JsonSerializer.Deserialize(root.GetRawText(), options), _ => JsonSerializer.Deserialize(root.GetRawText(), options) }, _ => null } ?? throw new JsonException($"{typeValue} 反序列化失败"); return instruct; } else { throw new JsonException("type property not found"); } } public override void Write(Utf8JsonWriter writer, Instruct value, JsonSerializerOptions options) { //JsonSerializer.Serialize(writer, (object)value, options); 这个在Data是对象时导致了无限递归调用 writer.WriteStartObject(); writer.WriteString(InstructNamingPolicy.Convert(nameof(Instruct.Type)), value.Type); if (value.Class != null) { writer.WriteString(InstructNamingPolicy.Convert(nameof(Instruct.Class)), value.Class); } if (value.Conveyor != null) { writer.WriteString(InstructNamingPolicy.Convert(nameof(Instruct.Conveyor)), value.Conveyor); } if (value.Time != null) { writer.WriteString(InstructNamingPolicy.Convert(nameof(Instruct.Time)), value.Time); } if (value.Data != null) { writer.WritePropertyName(InstructNamingPolicy.Convert(nameof(Instruct.Data))); JsonSerializer.Serialize(writer, value.Data, value.Data.GetType(), options); } writer.WriteEndObject(); } } public class Instruct { public static readonly JsonSerializerOptions options = new() { ReadCommentHandling = JsonCommentHandling.Skip, //允许注释 AllowTrailingCommas = true,//允许尾随逗号 PropertyNamingPolicy = new InstructNamingPolicy(), // 属性名为定制转换 DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, // 忽略 null 值 WriteIndented = true, // 美化输出 //PropertyNameCaseInsensitive = true,//属性名忽略大小写 Converters = { new InstructConverter() }, }; public string Type { get; set; } public string? Class { get; set; } public string? Conveyor { get; set; } public string? Time { get; set; } public dynamic? Data { get; set; } [JsonIgnore] public bool IsResponse { get; set; } = false; [JsonIgnore] public bool IsBroadcast { get; set; } = false; [JsonIgnore] public List ResponseOrBroadcastInstructs { get; set; } = new(); public Instruct() { this.Type = ""; } /// /// 指令处理逻辑 /// /// 将耗时任务交给Task以不阻塞单个连接的多个请求 public virtual Task Handler(string wsid) { return Task.CompletedTask; } public async Task HandlerAndMeasure(string wsid) { Stopwatch stopWatch = new(); stopWatch.Start(); await Handler(wsid); stopWatch.Stop(); GlobalArea.Log.Debug($"处理{this.GetType()}耗时:{stopWatch.ElapsedMilliseconds}ms"); } public string ToJsonString() { return JsonSerializer.Serialize(this, options); } public static Instruct? JsonStringParse(string jsonString) { try { return JsonSerializer.Deserialize(jsonString, options); } catch (Exception ex) { GlobalArea.Log.Error(ex.Message); return null; } } } }