You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
7.0 KiB
C#
169 lines
7.0 KiB
C#
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace OMS.NET.Instructs
|
|
{
|
|
/// <summary>
|
|
/// 声明json转换的命名策略
|
|
/// </summary>
|
|
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,
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 实现依据type和class的值决定反序列化的对象类型
|
|
/// </summary>
|
|
class InstructConverter : JsonConverter<Instruct>
|
|
{
|
|
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<GetPublickeyInstruct>(root.GetRawText(), options),
|
|
"get_serverImg" => JsonSerializer.Deserialize<GetServerImgInstruct>(root.GetRawText(), options),
|
|
"get_serverConfig" => JsonSerializer.Deserialize<GetServerConfigInstruct>(root.GetRawText(), options),
|
|
"login" => JsonSerializer.Deserialize<LoginInstruct>(root.GetRawText(), options),
|
|
"test" => JsonSerializer.Deserialize<TestInstruct>(root.GetRawText(), options),
|
|
"get_userData" => JsonSerializer.Deserialize<GetUserDataInstruct>(root.GetRawText(), options),
|
|
"get_presence" => JsonSerializer.Deserialize<GetPresenceInstruct>(root.GetRawText(), options),
|
|
"get_mapData" => JsonSerializer.Deserialize<GetMapDataInstruct>(root.GetRawText(), options),
|
|
"get_mapLayer" => JsonSerializer.Deserialize<GetMapLayerInstruct>(root.GetRawText(), options),
|
|
"ping" => JsonSerializer.Deserialize<PingInstuct>(root.GetRawText(), options),
|
|
|
|
//广播指令
|
|
"broadcast" => classValue switch
|
|
{
|
|
//广播指令继承结构
|
|
"point" => JsonSerializer.Deserialize<AddElementBroadcastInstruct>(root.GetRawText(), options),
|
|
"line" => JsonSerializer.Deserialize<AddElementBroadcastInstruct>(root.GetRawText(), options),
|
|
"area" => JsonSerializer.Deserialize<AddElementBroadcastInstruct>(root.GetRawText(), options),
|
|
"curve" => JsonSerializer.Deserialize<AddElementBroadcastInstruct>(root.GetRawText(), options),
|
|
_ => JsonSerializer.Deserialize<Instruct>(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<Instruct> ResponseOrBroadcastInstructs { get; set; } = new();
|
|
|
|
public Instruct()
|
|
{
|
|
this.Type = "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 指令处理逻辑
|
|
/// </summary>
|
|
/// <returns>将耗时任务交给Task以不阻塞单个连接的多个请求</returns>
|
|
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<Instruct>(jsonString, options);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
GlobalArea.Log.Error(ex.Message);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
} |