- 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,便于定位此类反射异常根因; 该信息仅写入日志,不返回前端
266 lines
7.9 KiB
C#
266 lines
7.9 KiB
C#
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.Type,Newtonsoft 序列化会触发
|
||
// "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; }
|
||
}
|
||
}
|