using Newtonsoft.Json; using System.Reflection; using System.Text.RegularExpressions; namespace HealthMonitor.Model.Service.Mapper { public class ParseTDengineRestResponse { #region 泛化解析 private List ParseDataList(dynamic data) { List result = new(); foreach (var row in data) { var model = CreateInstance(); for (int i = 0; i < ColumnMeta.Count; i++) { var columnName = ColumnMeta[i][0].ToString()!; var columnType = ColumnMeta[i][1].ToString()!; string pattern = @"\((.*?)\)"; // 匹配括号内的任意字符(非贪婪模式) // 使用正则表达式进行匹配 Match match = Regex.Match(columnName, pattern); // 检查是否有匹配项 if (match.Success) { // 提取括号内的内容 string contentInsideParentheses = match.Groups[1].Value; columnName = contentInsideParentheses; } var columnValue = ConvertValue(row[i], columnType!); SetProperty(model, columnName!, columnValue); } result.Add(model); } return result; } private static T CreateInstance() { return Activator.CreateInstance(); } private static void SetProperty(T target, string propertyName, TValue value) { var property = typeof(T).GetProperties() .FirstOrDefault(p => GetJsonPropertyName(p) == propertyName); if (property != null) { property.SetValue(target, value); } } private static object ConvertValue(object value, string columnType) { return columnType.ToUpper() switch { "TIMESTAMP" => DateTime.TryParse(value.ToString(),out DateTime dateTimeValue)? dateTimeValue:DateTime.Now, "NCHAR" or "VARCHAR" => value==null?string.Empty:value.ToString()!, "INT" => int.TryParse(value.ToString(), out int intValue)? intValue:0, "TINYINT" => Convert.ToByte(value), "BOOL" => Convert.ToBoolean(value), "FLOAT" => float.TryParse(value.ToString(), out float floatValue)? floatValue : 0f, _ => value, } ; } private static string GetJsonPropertyName(PropertyInfo property) { var attribute = (JsonPropertyAttribute)Attribute.GetCustomAttribute(property, typeof(JsonPropertyAttribute))!; return attribute?.PropertyName ?? property.Name; } private List ParseData = default!; #endregion #region 响应解析 [JsonProperty("code")] public int Code { get; set; } [JsonProperty("column_meta")] public List> ColumnMeta { get; set; } = new List>(); [JsonProperty("rows")] public int Rows { get; set; } [JsonProperty("data")] public dynamic Data { get => ParseData; set => ParseData = ParseDataList(value); } #endregion #region Linq public IEnumerable Select(Func selector) { return ParseData.Select(selector); } public IEnumerable Select() { return ParseData; } #endregion #region 统计算法 /// /// 统计算法 /// /// /// /// /// public float AverageAfterRemovingOneMinMaxRef(Func valueSelector, int numToRemove, out int[] collection, out int max, out int min) { var values = ParseData.Select(valueSelector).ToList(); collection = values.Select(i => (int)i).ToArray(); if (values.Count <= 2) { throw new ArgumentException("Not enough elements to remove."); } // Remove the specified number of minimum and maximum values //values.RemoveAll(_ => _ == values.Min()); //values.RemoveAll(_ => _ == values.Max()); max = (int)values.Max(); min = (int)values.Min(); values.Remove(max); values.Remove(min); // Remove values less than the specified threshold values.RemoveAll(_ => _ > numToRemove); // Calculate and return the average of the remaining values return values.Average(); } public decimal AverageAfterRemovingOneMinMaxRef(Func valueSelector, int refValue) { var values = ParseData.Select(valueSelector).ToList(); // Remove the specified number of minimum and maximum values //values.RemoveAll(_ => _ == values.Min()); //values.RemoveAll(_ => _ == values.Max()); values.Remove(values.Max()); values.Remove(values.Min()); // Remove values less than the specified threshold values.RemoveAll(_ => _ > refValue); if (values.Count < 2) { // throw new ArgumentException("数据不够不能计算"); // 平均值为0,说明数据不足,不能计算增量值 return 0M; } // Calculate and return the average of the remaining values return values.Average(); } #endregion } }