Files
zszq-trs/YLErpDAL/Modules/SuperviseReportModule/SAC/Common/Sac_TranslateHelper.cs
T
hjhan ca74095e0c fix(sac): 修复预览页序列化 SacInfo 时 TypeId 触发 IsGenericParameter 异常
- SacDescriptionAttribute 增加 ShouldSerializeTypeId() 返回 false,
  跳过 Attribute.TypeId(System.Type)的序列化,避免 Newtonsoft 抛
  "Method may only be called on a Type for which Type.IsGenericParameter is true."
  (13.0.1 安全版对 Type 成员序列化行为变更后暴露)
- ExceptionMiddleware 改用 exception.ToString() 记录完整异常(类型+
  内层 message+堆栈),替代仅取最内层 message,便于定位此类反射异常根因;
  该信息仅写入日志,不返回前端
2026-07-31 09:10:18 +08:00

266 lines
7.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Reflection;
using YLErp.Modules.SuperviseReportModule.SAC.Model;
namespace YLErp.Modules.SuperviseReportModule.SAC.Common
{
class Sac_TranslateHelper
{
private static SacMap? Map = null;
private static List<SacMap> GetSacInfo(PropertyInfo[] properties)
{
var result = new List<SacMap>();
foreach (var item in properties)
{
var sacInfo = new SacMap(item.Name, item.Name);
if (item.GetCustomAttributes(typeof(SacDescriptionAttribute)).FirstOrDefault() is SacDescriptionAttribute info)
{
sacInfo.FieldName = info.FieldName;
sacInfo.FieldName_CN = info.FieldName_CN;
sacInfo.FieldLength = info.FieldLength;
sacInfo.Required = info.Required;
sacInfo.FieldDescription = info.FieldDescription;
}
var att = item.PropertyType.GetGenericArguments();
if (att.Length == 0)
{
att = new[] { item.PropertyType };
}
if (att.Length == 1 && att[0].Namespace.StartsWith("YLErp.Modules.SuperviseReportModule"))
{
sacInfo.SubMaps.AddRange(GetSacInfo(att[0].GetProperties()));
}
//if(item.)
result.Add(sacInfo);
}
return result;
}
private static void Init()
{
Map = new SacMap("Root", "报文");
var root = typeof(ReportRootModel);
var properties = root.GetProperties();
Map.SubMaps.AddRange(GetSacInfo(properties));
}
public static SacMap TranslateFieldName(params string[] paths)
{
if (paths.Length == 0)
{
throw new ArgumentNullException(nameof(paths));
}
if (Map == null)
{
Init();
}
var map = Map;
foreach (var item in paths)
{
if (item == "Root")
{
continue;
}
if (map == null ||
map.SubMaps == null ||
(map = map.SubMaps.Where(O => O.FieldName == item).FirstOrDefault()) == null)
{
map = new SacMap(item, item);
}
}
return map;
}
public static string TranslateFieldName(string fieldName, string fileType = "")
{
if (Map == null)
{
Init();
}
SacMap map = Map;
return getFieldName_CN(map, fieldName, fileType);
}
private static string getFieldName_CN(SacMap map, string fieldName, string fileType = "")
{
if (map.FieldName == fieldName)
{
return map.FieldName_CN;
}
if (map.SubMaps.Count > 0)
{
foreach (var m in map.SubMaps)
{
if (map.FieldName == "Body")
{
if (!string.IsNullOrWhiteSpace(fileType) && m.FieldName != fileType)
{
continue;
}
}
var ret = getFieldName_CN(m, fieldName, fileType);
if (!string.IsNullOrWhiteSpace(ret))
{
return ret;
}
}
}
return "";
}
}
/// <summary>
/// 字段说明属性类
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class SacDescriptionAttribute : Attribute
{
// Attribute.TypeId 本质是 System.TypeNewtonsoft 序列化会触发
// "Method may only be called on a Type for which Type.IsGenericParameter is true."
// 预览页用 ToJson() 序列化 SacInfo/List<SacInfo> 时崩溃,故显式跳过该成员。
// 13.0.1 安全版对 Type 成员序列化行为变更后暴露此问题)
public bool ShouldSerializeTypeId() => false;
/// <summary>
/// 字段名
/// </summary>
public string FieldName { get; set; }
/// <summary>
/// 字段中文名
/// </summary>
public string FieldName_CN { get; set; }
/// <summary>
/// 字段长度
/// </summary>
public string FieldLength { get; set; }
/// <summary>
/// 必填
/// </summary>
public bool Required { get; set; }
/// <summary>
/// 字段说明
/// </summary>
public string FieldDescription { get; set; }
public SacDescriptionAttribute() { }
public SacDescriptionAttribute(string fieldName, string fieldName_CN, string fileLength, bool required, string fieldDescription)
{
FieldName = fieldName;
FieldName_CN = fieldName_CN;
FieldLength = fileLength;
Required = required;
FieldDescription = fieldDescription;
}
}
/// <summary>
/// 用于预览
/// </summary>
public class SacMap : SacDescriptionAttribute
{
/// <summary>
/// 子节点
/// </summary>
public List<SacMap> SubMaps { get; set; }
public SacMap() { }
public SacMap(string fieldName, string fieldName_CN)
{
FieldName = fieldName;
FieldName_CN = fieldName_CN;
SubMaps = new List<SacMap>();
}
public override string ToString()
{
return $"{FieldName}_{FieldDescription}_{SubMaps.Count}";
}
}
public class SacInfo : SacDescriptionAttribute
{
/// <summary>
/// 对象序号
/// </summary>
public int Index { get; set; }
/// <summary>
/// 值
/// </summary>
public string FieldValue { get; set; }
/// <summary>
/// 检查结果
/// </summary>
public string Message { get; set; }
/// <summary>
/// 子信息
/// </summary>
public List<SacInfo> SubMaps { get; set; }
public SacInfo()
{ }
public SacInfo(string fileName)
: this(fileName, "", "")
{
}
public SacInfo(string fileName, int index)
: this(fileName, "", "")
{
Index = index;
}
public SacInfo(string fileName, object value)
: this(fileName, value, "")
{
}
public SacInfo(string fileName, object value, string message)
{
FieldName = fileName;
FieldValue = (value as string) ?? "";
Message = message;
Index = -1;
SubMaps = new List<SacInfo>();
}
public void formatFieldDescription(params string[] paths)
{
var list = new List<string>(paths)
{
FieldName
};
var arr = list.ToArray();
var info = Sac_TranslateHelper.TranslateFieldName(arr);
FieldName = info.FieldName;
FieldName_CN = info.FieldName_CN;
FieldLength = info.FieldLength;
FieldDescription = info.FieldDescription;
Required = info.Required;
if (this.SubMaps != null && this.SubMaps.Count > 0)
{
SubMaps?.ForEach(O =>
{
if (O == null)
{
return;
}
O.formatFieldDescription(arr);
});
}
}
}
public class ExceptionExtensionInfo
{
public List<SacInfo> Tag { get; set; }
public string ErrFilePath { get; set; }
}
}