sunpengfei
2025-08-08 cd967e892418733e0bf4878c26f0cdb60c958120
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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.UserServer.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.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<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;
        }
    }
}