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.RequestTypeName,
it.ResponseTypeName
})
.FirstOrDefaultAsync();
if (model == null) throw Oops.Oh(EnumErrorCodeType.s404, "资源");
var requestType = App.Assemblies.SelectMany(it => it.GetTypes()).FirstOrDefault(it => it.FullName == model.RequestTypeName);
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(requestType, xmlDoc, []);
}
else if (requestType.Name.EndsWith("Command"))
{
return await GetFields(requestType, xmlDoc, []);
}
else if (model.ResponseTypeName.IsNotNull())
{
var responseType = Type.GetType(model.ResponseTypeName);
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;
}
}
}