using Furion; using Furion.DatabaseAccessor; using Furion.DataEncryption; using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.Extensions.Caching.Distributed; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Xml; namespace FlexJobApi.Core { /// /// 注释文档工具 /// public static class XmlDocUtils { private const string cacheKey = "XmlDoc"; public static XmlDoc XmlDoc { get; set; } /// /// 生成注释文档 /// /// public static async Task BuildXmlDocAsync() { var xmlDoc = new XmlDoc(); foreach (var item in App.Assemblies) { var path = item.Location.Replace("dll", "xml"); if (File.Exists(path)) { var document = new XmlDocument(); document.Load(path); var memberNodes = document.SelectNodes("//member"); if (memberNodes != null) { foreach (XmlNode memberNode in memberNodes) { var memberName = memberNode.Attributes?["name"]?.Value; if (!string.IsNullOrEmpty(memberName)) { var member = new XmlDocMember { Name = memberName, Summary = memberNode.SelectSingleNode("summary")?.InnerText?.Trim(), Returm = memberNode.SelectSingleNode("returns")?.InnerText?.Trim() }; var paramNodes = memberNode.SelectNodes("param"); if (paramNodes != null) { foreach (XmlNode paramNode in paramNodes) { var paramNodeName = paramNode.Attributes?["name"]?.Value; if (!string.IsNullOrEmpty(paramNodeName)) { member.Parameters.Add(new XmlDocMember { Name = paramNodeName, Summary = paramNode.InnerText?.Trim() }); } } } xmlDoc.Members.Add(member); } } } } } XmlDoc = xmlDoc; if (xmlDoc.Members.Any()) { var json = JsonConvert.SerializeObject(xmlDoc); await App.GetService().SetStringAsync(cacheKey, json); return xmlDoc; } return null; } /// /// 获取注释文档 /// /// public static async Task GetXmlDocAsync() { if (XmlDoc == null) { var json = await App.GetService().GetStringAsync(cacheKey); if (!string.IsNullOrEmpty(json)) { XmlDoc = JsonConvert.DeserializeObject(json); } if (XmlDoc == null) { XmlDoc = await BuildXmlDocAsync(); } } return XmlDoc; } /// /// 获取注释文档成员 /// /// /// /// public static async Task GetXmlDocMemberAsync(this MemberInfo memberInfo, XmlDoc xmlDoc = null) { if (xmlDoc == null) { xmlDoc = await GetXmlDocAsync(); } if (xmlDoc != null && memberInfo != null) { var memberName = GetXmlDocMemberName(memberInfo); return xmlDoc.Members.FirstOrDefault(it => it.Name == memberName); } return null; } private static string GetXmlDocMemberName(MemberInfo memberInfo) { if (memberInfo != null) { if (memberInfo is Type type) { return $"T:{GetTypeName(type)}"; } else if (memberInfo is MethodInfo methodInfo && methodInfo.DeclaringType != null) { var methodName = $"M:{GetTypeName(methodInfo.DeclaringType)}.{methodInfo.Name}"; var parameters = methodInfo.GetParameters(); if (parameters.Length > 0) { methodName += $"({string.Join(",", parameters.Select(p => GetTypeName(p.ParameterType)))})"; } return methodName; } else if (memberInfo is FieldInfo fieldInfo && fieldInfo.DeclaringType != null) { return $"F:{GetTypeName(fieldInfo.DeclaringType)}.{fieldInfo.Name}"; } else if (memberInfo is PropertyInfo propertyInfo && propertyInfo.DeclaringType != null) { return $"P:{GetTypeName(propertyInfo.DeclaringType)}.{propertyInfo.Name}"; } } return string.Empty; } private static string GetTypeName(Type type) { if (type.IsGenericType) { var genericTypeDefinition = type.GetGenericTypeDefinition(); var genericArguments = type.GetGenericArguments(); var baseName = genericTypeDefinition.FullName?.Replace('+', '.') ?? ""; baseName = baseName.Substring(0, baseName.IndexOf('`')); return $"{baseName}`{genericArguments.Length}"; } else if (type.IsArray) { var elementType = type.GetElementType(); if (elementType != null) { return $"{GetTypeName(elementType)}[]"; } } else if (type.IsNested && type.DeclaringType != null) { return $"{GetTypeName(type.DeclaringType)}+{type.Name}"; } return type.FullName?.Replace('+', '.') ?? ""; } } }