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
|
{
|
/// <summary>
|
/// 获取资源字段
|
/// </summary>
|
public class GetResourceFieldsQueryHandler(
|
IRepository<Resource> rep
|
) : IRequestHandler<GetResourceFieldsQuery, List<GetResourceFieldsQueryResultItem>>
|
{
|
private readonly IRepository<Resource> rep = rep;
|
|
/// <inheritdoc/>
|
public async Task<List<GetResourceFieldsQueryResultItem>> Handle(GetResourceFieldsQuery request, CancellationToken cancellationToken)
|
{
|
var a = App.GetService<IHttpContextAccessor>();
|
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(pagedListItemType, 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<List<GetResourceFieldsQueryResultItem>> GetFields(Type type, XmlDoc xmlDoc, HashSet<Type> processedTypes)
|
{
|
var fields = new List<GetResourceFieldsQueryResultItem>();
|
|
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;
|
}
|
}
|
}
|