using FlexJobApi.Core; using Furion; using Furion.DatabaseAccessor; using Furion.FriendlyException; using MediatR; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.User.Application { /// /// 获取资源字段 /// public class GetResourceFieldsQueryHandler( IRepository rep ) : IRequestHandler> { private readonly IRepository rep = rep; /// public async Task> Handle(GetResourceFieldsQuery request, CancellationToken cancellationToken) { var a = App.GetService(); var b = JwtUtils.GetCurrentLogier(); var model = await rep.AsQueryable().AsNoTracking() .Where(it => it.Id == request.Id) .Select(it => new { it.RequestTypeFullName, it.ResponseTypeFullName }) .FirstOrDefaultAsync(); if (model == null) throw Oops.Oh(EnumErrorCodeType.s404, "资源"); var requestType = App.Assemblies.SelectMany(it => it.GetTypes()).FirstOrDefault(it => it.FullName == model.RequestTypeFullName); if (requestType == null) throw Oops.Oh(EnumErrorCodeType.s404, "资源"); var xmlDoc = await XmlDocUtils.GetXmlDocAsync(); if (requestType.BaseType?.IsGenericType == true && requestType.BaseType.GetGenericTypeDefinition() == typeof(PagedListQuery<,>)) { var pagedListItemType = requestType.BaseType.GenericTypeArguments[1]; return await GetFields(pagedListItemType, xmlDoc, []); } else if (requestType.Name.EndsWith("Command")) { return await GetFields(requestType, xmlDoc, []); } else if (model.ResponseTypeFullName.IsNotNull()) { var responseType = Type.GetType(model.ResponseTypeFullName); if (responseType == null) throw Oops.Oh(EnumErrorCodeType.s404, "资源"); return await GetFields(responseType, xmlDoc, []); } return []; } private async Task> GetFields(Type type, XmlDoc xmlDoc, HashSet processedTypes) { var fields = new List(); if (type.IsGenericType) { type = type.GenericTypeArguments[0]; } // 过滤无效类型(null、非类、不含目标命名空间) if (type == null || !type.IsClass || type.FullName == null || !type.FullName.Contains("FlexJobApi")) { return fields; } // 关键:如果类型已处理过,直接返回(避免循环引用死循环) if (processedTypes.Contains(type)) { return fields; } // 将当前类型标记为已处理 processedTypes.Add(type); // 获取当前类型的所有公共属性 var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in props) { var item = new GetResourceFieldsQueryResultItem(); var propXmlDoc = await prop.GetXmlDocMemberAsync(xmlDoc); item.Code = prop.Name; item.Name = propXmlDoc?.Summary; fields.Add(item); // 递归获取子属性的字段(传入已处理集合,避免死循环) var childrenFields = await GetFields(prop.PropertyType, xmlDoc, processedTypes); if (childrenFields.Any()) { var childrens = childrenFields .Select(it => new GetResourceFieldsQueryResultItem { Code = $"{item.Code}.{it.Code}", Name = it.Name }) .ToList(); fields.AddRange(childrens); } } // 移除当前类型的标记(允许其他分支重新处理,如不同路径下的同一类型) processedTypes.Remove(type); return fields; } } }