说明

既然是反射,那就来一个彻底一点的!
我们不是要给对应的Entity写AppService作为RUSTAPI么
那可不可以不写,用统一的?
需要个性化的再写!
这个需求是可以的!
把下面这个放在项目的XXX.Application项目下,结合自己的项目进行调整即可!

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PasteForm.Application.Contracts;
using PasteForm.Handler;
using PasteForm.usermodels;
using PasteFormHelper;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.Dynamic;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.Json.Nodes;
using System.Web;
using Volo.Abp.Auditing;

namespace PasteForm.Application
{
    /// <summary>
    /// 默认读取 这个很关键,实现了统一的新增 更新 详细 列表规范读取 相当于兜底的!
    /// Version.2025.07.06.02
    /// 当前还有一个问题,就是Page不是采用LeftJoin的,是分次查询,因为LeftJoin的组合有问题,目前还在找办法,Queryable死活会被转换成DbSet... .. .
    ///</summary>
    [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
    [DisableAuditing]
    public class DefaultAppService : PasteFormAppService
    {

        #region 以下是具体实现 Version.2025.07.03

        /// <summary>
        /// 读取AddDto的数据模型 用于新增
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
        [Route("/api/app/{entityName}/readAddModel", Order = 10)]
        public VoloModelInfo ReadAddModel([FromRoute] string entityName)
        {
            // 1. 根据实体名称查找对应的实体类型和 DTO 类型
            var entityType = FindEntityType(entityName);
            if (entityType == null)
            {
                throw new PasteCodeException($"找不到对应的实体类型: {entityName}");
            }
            var dtoType = FindDtoType(entityName, "AddDto");

            if (dtoType == null)
            {
                throw new PasteCodeException($"找不到对应的 DTO 类型: {entityName}AddDto");
            }

            //new一个出来
            var dto = Activator.CreateInstance(dtoType);

            // 4. 动态读取 DTO 的属性信息
            var dataModel = ReadModelProperties(dto, dtoType);

            return dataModel;

        }

        /// <summary>
        /// 用于更新表单
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        [HttpGet]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
        [Route("/api/app/{entityName}/{id}/readUpdateModel", Order = 10)]
        public async Task<VoloModelInfo> ReadUpdateModel([FromRoute] string entityName, [FromRoute] int id)
        {
            // 1. 根据实体名称查找对应的实体类型和 DTO 类型
            var entityType = FindEntityType(entityName);
            var dtoType = FindDtoType(entityName, "UpdateDto");

            if (entityType == null || dtoType == null)
            {
                throw new PasteCodeException($"找不到对应的实体或 DTO 类型: {entityName}");
            }
            // 2. 动态查询实体
            var entity = await FindEntityByIdAsync(entityType, id);
            if (entity == null)
            {
                throw new PasteCodeException("查询的信息不存在,无法执行编辑操作!");
            }
            // 3. 动态映射实体到 DTO
            var dto = MapEntityToDto(entity, entityType, dtoType);

            //构建外表等 Include的如何搞定???
            await BuildOuterQuery(dto, dtoType);

            // 4. 动态读取 DTO 的属性信息
            var dataModel = ReadModelProperties(dto, dtoType);
            return dataModel;
        }

        /// <summary>
        /// 用于查看详情
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("/api/app/{entityName}/{id}/readDetailModel", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
        public async Task<VoloModelInfo> ReadDetailModel([FromRoute] string entityName, [FromRoute] int id)
        {
            //var _info = await _dbContext.StoreCashWay.Where(x => x.Id == id).AsNoTracking().FirstOrDefaultAsync();
            //if (_info == null || _info == default)
            //{
            //    throw new PasteCodeException("查询的信息不存在,无法执行编辑操作!");
            //}
            //var dto = ObjectMapper.Map<StoreCashWay, StoreCashWayDto>(_info);
            //var _dataModel = PasteBuilderHelper.ReadModelProperty<StoreCashWayDto>(dto);
            //return _dataModel;

            // 1. 根据实体名称查找对应的实体类型和 DTO 类型
            var entityType = FindEntityType(entityName);
            var dtoType = FindDtoType(entityName, "Dto");

            if (entityType == null || dtoType == null)
            {
                throw new PasteCodeException($"找不到对应的实体或 DTO 类型: {entityName}");
            }

            // 2. 动态查询实体
            var entity = await FindEntityByIdAsync(entityType, id);
            if (entity == null)
            {
                throw new PasteCodeException("查询的信息不存在,无法执行编辑操作!");
            }

            // 3. 动态映射实体到 DTO
            var dto = MapEntityToDto(entity, entityType, dtoType);

            //构建外表等 Include的如何搞定???
            await BuildOuterQuery(dto, dtoType);

            // 4. 动态读取 DTO 的属性信息
            var dataModel = ReadModelProperties(dto, dtoType);

            return dataModel;

        }

        /// <summary>
        /// 用户查看表格
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("/api/app/{entityName}/readListModel", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
        public VoloModelInfo ReadListModel([FromRoute] string entityName, string searchName = "InputSearchBase")
        {
            // 动态查找实体对应的 ListDto 类型
            var listDtoType = FindDtoType(entityName, "ListDto");
            // 创建 ListDto 实例
            var listDtoInstance = Activator.CreateInstance(listDtoType);
            // 动态读取 ListDto 的属性信息
            //var listModel = PasteBuilderHelper.ReadModelProperty(listDtoInstance, true);
            var listModel = ReadModelProperties(listDtoInstance, listDtoType, true);
            if (searchName != "InputSearchBase")
            {
                // 保持搜索模型的静态处理(假设 InputSearchBase 是固定类)
                var searchModel = PasteBuilderHelper.ReadModelProperty(new InputSearchBase());
                if (searchModel != null)
                {
                    listModel.QueryProperties = searchModel.Properties;
                }
            }
            else
            {
                var search_type = FindType(searchName);
                if (search_type != null)
                {
                    var search_model = Activator.CreateInstance(search_type);
                    //var searchModel = PasteBuilderHelper.ReadModelProperty(search_model);
                    var searchModel = ReadModelProperties(search_model, search_type, true);
                    if (searchModel != null)
                    {
                        listModel.QueryProperties = searchModel.Properties;
                    }
                }
            }
            return listModel;
        }

        /// <summary>
        /// 简单按页查询 不涉及Left Join等
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="searchName"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        [HttpGet]
        [Route("/api/app/{entityName}/page", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
        public async Task<dynamic> Page([FromRoute] string entityName, string searchName = "InputSearchBase")
        {
            // [FromQuery] InputSearchBase input
            // 1. 根据实体名称查找对应的实体类型和DTO类型
            var entityType = FindEntityType(entityName);
            var listDtoType = FindDtoType(entityName, "ListDto");

            if (entityType == null || listDtoType == null)
            {
                throw new PasteCodeException($"找不到对应的实体或DTO类型: {entityName}", 404);
            }

            var query_string = base._httpContext.Request.QueryString.ToString();
            var querys = query_string.ToQuerys();
            foreach (var key in querys.Keys)
            {
                querys[key] = HttpUtility.UrlDecode(querys[key]);
            }
            var query_body = JsonConvert.SerializeObject(querys);
            //获取基础的
            var input = JsonConvert.DeserializeObject<InputSearchBase>(query_body);
            //Console.WriteLine("line.219");
            Type searchType = null;
            object searchObject = null;

            if (searchName != "InputSearchBase")
            {
                searchType = FindType(searchName);
                searchObject = JsonConvert.DeserializeObject(query_body, searchType);
                //未完待续,后续扩展,更多其他字段查询
            }
            //Console.WriteLine("line.229");
            IQueryable query = null;

            if (searchName == "InputSearchBase")
            {
                // 2. 动态构建查询
                query = BuildDynamicQuery(entityType, input);
            }
            else
            {
                query = BuildDynamicQuery(entityType, searchType, searchObject);
            }
            // 3. 计算总记录数(仅第一页需要)
            //var pagedDtoType = typeof(PagedResultDto<>).MakeGenericType(listDtoType);
            //dynamic pagedDto = Activator.CreateInstance(pagedDtoType);
            //Console.WriteLine("line.244");
            dynamic pagedto = new ExpandoObject();

            if (input.page == 1)
            {
                pagedto.totalCount = await ExecuteCountQuery(query, entityType);
            }

            if (searchName == "InputSearchBase")
            {
                query = ApplyPagingAndSorting(query, entityType, input);
                // 4. 应用分页和排序
                //var pagedQuery = ApplyPagingAndSorting(query, entityType, input);
            }
            else
            {
                query = ApplyPagingAndSorting(query, entityType, searchType, searchObject);
            }
            // 5. 执行查询并获取结果
            //var entities = await ExecuteQuery(query, entityType);
            //if (entities == null || entities.Count == 0)
            //{
            //    return null;
            //}
            //var dtos = MapEntitiesToDtos(entities, entityType, listDtoType);

            var dtos = await ExecuteProjectionQuery(query, entityType, listDtoType);
            if (dtos?.Any() == false)
            {
                return null;
            }

            // 6. 动态映射实体到DTO


            //查询外表 并实现 这里是简单的外表ID的查询 如果有更复杂的,还需要实现
            await BuildOuterData(listDtoType, dtos);
            // 7. 设置结果并返回
            //pagedDto.Items = dtos.Cast<object>().ToList();
            pagedto.items = dtos;
            return pagedto;
        }

        /// <summary>
        /// 通用创建方法
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        [HttpPost]
        [Route("/api/app/{entityName}/item", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "add" })]
        public async Task<dynamic> CreateItemAsync([FromRoute] string entityName, [FromBody] JsonObject input)
        {
            // 获取实体类型和添加DTO类型
            var entityType = FindEntityType(entityName);
            var addDtoType = FindDtoType(entityName, "AddDto");

            if (entityType == null || addDtoType == null)
            {
                throw new PasteCodeException($"找不到对应的实体或添加DTO类型: {entityName}", 404);
            }
            ////Console.WriteLine($"line.769 {input.ToString()} {input.ToJsonString()}");
            // 反序列化输入数据到添加DTO
            var addDto = JsonConvert.DeserializeObject(input.ToJsonString(), addDtoType);
            ValidateModel(addDto, addDtoType);



            // 创建实体实例
            var entity = Activator.CreateInstance(entityType);

            // 映射DTO到实体
            MapProperties(addDto, entity, addDtoType, entityType);


            //填充预定值
            //foreach (var pro in entityType.GetProperties())
            //{
            //    switch (pro.Name)
            //    {
            //        case "UserId":
            //        case "CreateUserId":
            //            {
            //                var user_id = base.ReadCurrentUserId();
            //                SetPropertyValue(entity, pro.Name, user_id);
            //            }
            //            break;
            //        default:
            //            break;
            //    }
            //}

            //下面这个和上面注释的意思一样
            base.DefaultBeforeCreate(entityType.GetProperties(),entity);

            // 添加到数据库
            var dbSet = GetDbSet(entityType);
            dbSet.GetType().GetMethod("Add").Invoke(dbSet, new[] { entity });

            // 保存更改
            await _dbContext.SaveChangesAsync();
            //Console.WriteLine("line.869");
            var find_id = entityType.GetProperties().Where(x => x.Name == "Id").FirstOrDefault();
            if (find_id != null && find_id != default)
            {
                return find_id.GetValue(entity).ToString();
            }

            return null;

            //// 映射实体到返回DTO
            //var returnDtoType = FindDtoType(entityName, "Dto");
            //var returnDto = Activator.CreateInstance(returnDtoType);
            //MapProperties(entity, returnDto, entityType, returnDtoType);

            //return returnDto;
        }

        /// <summary>
        /// 通用更新方法
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        [HttpPost]
        [Route("/api/app/{entityName}/updateItem", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "edit" })]
        public async Task<object> UpdateItemAsync([FromRoute] string entityName, [FromBody] JsonObject input)
        {
            // 获取实体类型和更新DTO类型
            var entityType = FindEntityType(entityName);
            var updateDtoType = FindDtoType(entityName, "UpdateDto");

            if (entityType == null || updateDtoType == null)
            {
                throw new PasteCodeException($"找不到对应的实体或更新DTO类型: {entityName}", 404);
            }

            // 反序列化输入数据到更新DTO
            var updateDto = JsonConvert.DeserializeObject(input.ToString(), updateDtoType);

            // 手动执行模型验证
            ValidateModel(updateDto, updateDtoType);

            // 获取ID属性值
            var id = GetPropertyValue(updateDto, "Id");
            if (id == null)
            {
                throw new PasteCodeException("更新DTO必须包含Id属性", 400);
            }

            // 查找实体
            var entity = await FindEntityByIdAsync(entityType, id);
            if (entity == null)
            {
                throw new PasteCodeException("需要更新的记录不存在", 404);
            }

            // 映射DTO到实体
            MapProperties(updateDto, entity, updateDtoType, entityType);

            //foreach (var pro in entityType.GetProperties())
            //{
            //    switch (pro.Name)
            //    {
            //        case "UpdateTime":
            //        case "UpdateDate":
            //            {
            //                SetPropertyValue(entity, pro.Name, DateTime.Now);
            //            }
            //            break;
            //        default:
            //            break;
            //    }
            //}
            //下面这个和上面注释的意思一样
            base.DefaultBeforeUpdate(entityType.GetProperties(), entity);


            // 保存更改
            await _dbContext.SaveChangesAsync();


            //var find_id = entityType.GetProperties().Where(x => x.Name == "Id").FirstOrDefault();
            //if (find_id != null && find_id != default)
            //{
            //    return find_id.GetValue(dbSet);
            //}

            return id;

            //// 映射实体到返回DTO
            //var returnDtoType = FindDtoType(entityName, "Dto");
            //var returnDto = Activator.CreateInstance(returnDtoType);
            //MapProperties(entity, returnDto, entityType, returnDtoType);

            //return returnDto;
        }

        /// <summary>
        /// 通用状态更新方法
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        [HttpPost]
        [Route("/api/app/{entityName}/updateState", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "state" })]
        public async Task<string> UpdateState([FromRoute] string entityName, [FromBody] InputQueryUpdateState input)
        {
            // 获取实体类型
            var entityType = FindEntityType(entityName);

            if (entityType == null)
            {
                throw new PasteCodeException($"找不到对应的实体类型: {entityName}", 404);
            }

            // 解析ID
            if (!int.TryParse(input.id, out var id))
            {
                throw new PasteCodeException("提供的参数id错误,无法继续执行", 400);
            }

            // 查找实体
            var entity = await FindEntityByIdAsync(entityType, id);
            if (entity == null)
            {
                throw new PasteCodeException("没有找到对应的操作对象,无法继续执行", 404);
            }

            // 获取实体的所有布尔类型属性
            var booleanProperties = entityType.GetProperties()
                .Where(p => p.PropertyType == typeof(bool) || p.PropertyType == typeof(bool?))
                .ToDictionary(p => p.Name, p => p);

            //if (!booleanProperties.ContainsKey(input.name.ToLower()))
            //{
            //    throw new PasteCodeException($"实体 {entityName} 中不存在布尔属性: {input.name}", 400);
            //}
            //input.name isEnable转 IsEnable
            var current_pro = ConvertToPascalCase(input.name);
            if (booleanProperties.ContainsKey(current_pro))
            {
                // 获取属性信息并更新值
                var property = booleanProperties[current_pro];
                if (!property.CanWrite)
                {
                    throw new PasteCodeException($"属性 {input.name} 不可写", 400);
                }

                // 处理可空布尔类型
                if (property.PropertyType == typeof(bool?))
                {
                    property.SetValue(entity, input.state ? (bool?)true : (bool?)false);
                }
                else
                {
                    property.SetValue(entity, input.state);
                }
                // 保存更改
                await _dbContext.SaveChangesAsync();
            }
            else
            {
                Logger.LogWarning($"没有找到这个字段信息:{current_pro} {input.name}");
            }



            return "提交成功";
        }

        /// <summary>
        /// 通用删除 遵照ListDto的PasteDisable特性
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        [HttpPost]
        [Route("/api/app/{entityName}/remove", Order = 10)]
        [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "del" })]
        public async Task<string> Remove([FromRoute] string entityName, [FromQuery] int id)
        {
            // 获取实体类型
            var entityType = FindEntityType(entityName);

            if (entityType == null)
            {
                throw new PasteCodeException($"找不到对应的实体类型: {entityName}", 404);
            }

            var listDtoType = FindDtoType(entityName, "ListDto");
            if (listDtoType != null)
            {
                var finds = listDtoType.GetCustomAttributes<PasteDisableAttribute>();
                if (finds?.Any() == true)
                {
                    var find = finds.FirstOrDefault();
                    if (find.Args3 == "del")
                    {
                        throw new PasteCodeException($"实体 {entityName} 不允许删除操作", 403);
                    }
                }
            }

            // 查找实体
            var entity = await FindEntityByIdAsync(entityType, id);
            if (entity == null)
            {
                throw new PasteCodeException("需要删除的记录不存在", 404);
            }

            // 执行删除操作
            var dbSet = GetDbSet(entityType);
            dbSet.GetType().GetMethod("Remove").Invoke(dbSet, new[] { entity });

            // 保存更改
            await _dbContext.SaveChangesAsync();

            return "删除成功";
        }


        #region 以下是辅助函数

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="dtoType"></param>
        /// <returns></returns>
        private async Task BuildOuterQuery(object dto, Type dtoType)
        {
            #region 看看是否要执行外表查询
            foreach (var aty in dtoType.GetProperties())
            {
                //var _type = aty.PropertyType;
                var attributes = aty.GetCustomAttributes<PasteShortAttribute>();
                if (attributes?.Any() == true)
                {
                    var short_attr = attributes.FirstOrDefault();
                    if (short_attr != null && short_attr != default)
                    {
                        var foreignKeyId = aty.GetValue(dto);
                        if (foreignKeyId == null || foreignKeyId.Equals(0))
                        {
                            continue;
                        }
                        var shortAttr = short_attr;
                        //var pro_val =//??? 当前字段的值
                        //short_attr.Args1 = "GradeInfo";//表示对应的外表的EntityName
                        //short_attr.Args2 = "ExtendGrade";//表示结果写入到这个字段
                        //short_attr.Args3 = "ToShortUser()";//表示要转换的类型 比如_dbContext.GradeInfo.Where(x=>x.Id==pro_val).Select(x=>x.ToShortUser()).FirstOrDefaultAsync();
                        //如何获取字段的当前值?
                        //await _dbContext.GradeInfo.Where(x => x.Id == 1).Select(y => y.ToShortGrade()).FirstOrDefaultAsync();
                        //ToShortGrade()是GradeInfo的扩展,返回的就是ExtendGrade的类型

                        // 获取外表的Entity类型和目标属性
                        var relatedEntityType = FindEntityType(shortAttr.Args1);
                        var targetProperty = dtoType.GetProperty(shortAttr.Args2);

                        if (relatedEntityType == null || targetProperty == null)
                        {
                            continue;
                        }
                        try
                        {
                            // 获取关联实体的DbSet
                            var dbSet = _dbContext.GetType()
                                .GetProperties()
                                .First(p => p.PropertyType.GenericTypeArguments.Contains(relatedEntityType))
                                .GetValue(_dbContext);

                            // 动态调用FindAsync方法获取关联实体
                            var findAsyncMethod = dbSet.GetType()
                                .GetMethod("FindAsync", new[] { typeof(object[]) });

                            // 执行查询
                            var valueTask = findAsyncMethod.Invoke(dbSet, new object[] { new object[] { foreignKeyId } });

                            // 获取ValueTask的结果
                            object relatedEntity;

                            // 检查是否是ValueTask
                            if (valueTask.GetType().Name.StartsWith("ValueTask"))
                            {
                                // 手动获取ValueTask的结果
                                var getAwaiterMethod = valueTask.GetType().GetMethod("GetAwaiter");
                                var awaiter = getAwaiterMethod.Invoke(valueTask, null);

                                var getResultMethod = awaiter.GetType().GetMethod("GetResult");
                                relatedEntity = getResultMethod.Invoke(awaiter, null);
                            }
                            else
                            {
                                // 普通Task,直接等待
                                await (Task)valueTask;
                                relatedEntity = ((Task<object>)valueTask).Result;
                            }


                            if (relatedEntity != null)
                            {
                                // 处理转换逻辑
                                object convertedResult = null;

                                // 检查是否需要特殊转换
                                if (!string.IsNullOrEmpty(shortAttr.Args3))
                                {
                                    var extend = typeof(LinqExtend).GetMethod(shortAttr.Args3.Replace("()", ""), new[] { relatedEntityType });
                                    // 处理特殊转换方法(例如:ToShortUser())
                                    //convertedResult = ConvertEntity(relatedEntity, relatedEntityType, shortAttr.Args3);
                                    convertedResult = extend.Invoke(null, new object[] { relatedEntity });
                                }
                                else
                                {
                                    // 默认转换:直接使用目标属性类型
                                    convertedResult = relatedEntity;
                                }

                                // 设置目标属性的值
                                targetProperty.SetValue(dto, convertedResult);
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.LogError(ex, $"加载关联数据失败: {shortAttr.Args1}");
                            // 可以选择记录错误但继续处理其他属性
                        }
                        //------------------------------------------------
                    }
                }
            }

            #endregion
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        private Type FindEntityType(string entityName)
        {
            // 将前端传递的名称转换为 PascalCase (例如: storeCashWay -> StoreCashWay)
            var pascalCaseName = ConvertToPascalCase(entityName);
            var assembly = typeof(UserInfo).Assembly;//这里对不对呢... .. .
            return assembly.GetTypes().FirstOrDefault(t => t.Name == entityName || t.Name == $"{pascalCaseName}");//这里可能有问题了

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        private Type FindDtoType(string entityName, string suffix)
        {
            var pascalCaseName = ConvertToPascalCase(entityName);
            var dtoName = $"{pascalCaseName}{suffix}";

            return typeof(InputSearchBase).Assembly.GetTypes().FirstOrDefault(t => t.Name == dtoName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="typeName"></param>
        /// <returns></returns>
        private Type FindType(string typeName)
        {
            var assembly = Assembly.GetExecutingAssembly();
            //return assembly.GetTypes().FirstOrDefault(t => t.Name == typeName);
            return typeof(InputSearchBase).Assembly.GetTypes().FirstOrDefault(t => t.Name == typeName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private async Task<object> FindEntityByIdAsync(Type entityType, object id, CancellationToken cancellationToken = default)
        {
            // 获取实体对应的 DbSet 属性
            var dbSetProperty = _dbContext.GetType()
                .GetProperties()
                .FirstOrDefault(p =>
                    p.PropertyType.IsGenericType &&
                    p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
                    p.PropertyType.GetGenericArguments()[0] == entityType);

            if (dbSetProperty == null)
            {
                throw new PasteCodeException($"找不到实体 {entityType.Name} 的 DbSet");
            }

            // 获取 DbSet 实例
            var dbSet = dbSetProperty.GetValue(_dbContext);

            // 获取 FindAsync 方法
            var findAsyncMethod = dbSet.GetType()
                .GetMethod("FindAsync", new[] { typeof(object[]), typeof(CancellationToken) });

            // 调用方法
            var valueTask = findAsyncMethod.Invoke(dbSet, new object[] { new object[] { id }, cancellationToken });

            // 处理 ValueTask<T>
            if (valueTask is Task task)
            {
                await task;
                var resultProperty = task.GetType().GetProperty("Result");
                return resultProperty.GetValue(task);
            }
            else
            {
                // 手动处理 ValueTask<T>
                var getAwaiterMethod = valueTask.GetType().GetMethod("GetAwaiter");
                var awaiter = getAwaiterMethod.Invoke(valueTask, null);

                var getResultMethod = awaiter.GetType().GetMethod("GetResult");
                return getResultMethod.Invoke(awaiter, null);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceType"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        private MethodInfo GetMapMethod(Type sourceType, Type destinationType)
        {
            // 获取 Map<TSource, TDestination> 方法定义
            var map = base.ObjectMapper;
            var mapMethod = typeof(Volo.Abp.ObjectMapping.IObjectMapper)
                .GetMethods(BindingFlags.Public | BindingFlags.Instance)
                .FirstOrDefault(m =>
                    m.Name == "Map" &&
                    m.IsGenericMethodDefinition &&
                    m.GetGenericArguments().Length == 2 &&
                    m.GetParameters().Length == 1
                );

            if (mapMethod == null)
            {
                throw new InvalidOperationException("未找到 Map<TSource, TDestination> 方法");
            }

            // 构造具体的泛型方法
            return mapMethod.MakeGenericMethod(sourceType, destinationType);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceInstance"></param>
        /// <param name="sourceType"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public object MapEntityToDto(object sourceInstance, Type sourceType, Type destinationType)
        {
            // 获取 ObjectMapper 实例
            var mapper = ObjectMapper;

            // 获取映射方法
            var mapMethod = GetMapMethod(sourceType, destinationType);

            // 调用映射方法
            return mapMethod.Invoke(ObjectMapper, new object[] { sourceInstance });
        }

        /// <summary>
        /// 动态读取模型属性
        /// </summary>
        /// <param name="model"></param>
        /// <param name="modelType"></param>
        /// <param name="IsListModel">针对枚举的备注过滤</param>
        /// <returns></returns>
        private VoloModelInfo ReadModelProperties(object model, Type modelType, bool IsListModel = false)
        {
            // 获取目标泛型方法定义
            var genericMethodDefinition = typeof(PasteBuilderHelper)
                .GetMethods(BindingFlags.Public | BindingFlags.Static)
                .First(m => m.Name == "DynamicReadModelProperty" && m.IsGenericMethodDefinition);

            // 构建具体的泛型方法(传入实际类型参数)
            var constructedGenericMethod = genericMethodDefinition
                .MakeGenericMethod(modelType);

            // 调用方法并转换结果
            return (VoloModelInfo)constructedGenericMethod
                .Invoke(null, new object[] { model, IsListModel });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private string ConvertToPascalCase(string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return input;
            }
            if (char.IsUpper(input[0]))
            {
                return input;
            }
            return input.Substring(0, 1).ToUpper() + input.Substring(1);
        }

        #endregion



        /// <summary>
        /// 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="modelType"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="PasteCodeException"></exception>
        private void ValidateModel(object model, Type modelType)
        {
            if (model == null)
                throw new ArgumentNullException(nameof(model));

            var validationResults = new List<ValidationResult>();
            var validationContext = new ValidationContext(model);

            if (!Validator.TryValidateObject(model, validationContext, validationResults, true))
            {
                var errorMessages = validationResults
                    .SelectMany(r => r.MemberNames.Select(n => $"{n}: {r.ErrorMessage}"))
                    .ToList();

                throw new PasteCodeException("输入数据验证失败", 400);
            }
            else
            {
                //Console.WriteLine($"{modelType.FullName} 验证通过!");
            }
        }

        /// <summary>
        /// 补充Extend外表查询 比如ExtendUser 可能有多个
        /// </summary>
        /// <param name="listDtoType"></param>
        /// <param name="dtos"></param>
        /// <returns></returns>
        private async Task BuildOuterData(Type listDtoType, List<object> dtos)
        {
            var sears = listDtoType.GetProperties().Where(x => x.GetCustomAttributes<PasteShortAttribute>().Any()).ToList();
            if (sears?.Any() == true)
            {
                foreach (var _search in sears)
                {
                    var short_attr = _search.GetCustomAttributes<PasteShortAttribute>().FirstOrDefault();
                    if (short_attr != null && short_attr != default)
                    {
                        var out_id_field = _search.Name;//UserId
                        var out_entity_name = short_attr.Args1;//UserInfo
                        var to_extend = short_attr.Args2;//ExtendUser

                        var target_property = listDtoType.GetProperties().Where(x => x.Name == to_extend).FirstOrDefault();
                        if (target_property == null || target_property == default)
                        {
                            continue;
                        }

                        var relatedDtoType = target_property.PropertyType;

                        var ids = new HashSet<object>();
                        foreach (var dto in dtos)
                        {
                            var id = dto.GetType().GetProperty(out_id_field)?.GetValue(dto);
                            if (id != null)
                            {
                                ids.Add(id);
                            }
                        }
                        if (ids.Count > 0)
                        {
                            //从数据库读取数据
                            var relatedEntityType = FindEntityType(out_entity_name);
                            //转换成对应的dto
                            //赋值
                            if (relatedEntityType == null)
                            {
                                continue;
                            }

                            // 构建ID查询条件
                            var relatedQuery = BuildIdQuery(relatedEntityType, ids);

                            //先查询出Entitys再Mapper
                            //var relatedEntities = await ExecuteQuery(relatedQuery, relatedEntityType);
                            //if (relatedEntities?.Any() == false)
                            //{
                            //    continue;
                            //}
                            //var relatedDtos = MapEntitiesToDtos(relatedEntities, relatedEntityType, relatedDtoType);
                            //直接查询Dto
                            var relatedDtos = await ExecuteProjectionQuery(relatedQuery, relatedEntityType, relatedDtoType);

                            // 3. 创建ID到DTO的映射字典
                            var idToDto = relatedDtos.ToDictionary(d => d.GetType().GetProperty("Id")?.GetValue(d));

                            // 4. 填充到主表DTO
                            foreach (var dto in dtos)
                            {
                                //获取UserId的值
                                var id = dto.GetType().GetProperty(out_id_field)?.GetValue(dto);
                                if (id != null && idToDto.TryGetValue(id, out var relatedDto))
                                {
                                    //给ExtendUser填充值
                                    dto.GetType().GetProperty(to_extend)?.SetValue(dto, relatedDto);
                                }
                            }

                        }

                    }
                }
            }
        }


        #region Page的辅助方法

        /// <summary>
        /// 动态构建查询的方法
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        private IQueryable BuildDynamicQuery(Type entityType, InputSearchBase input)
        {
            // 获取DbSet方法
            var dbSetMethod = _dbContext.GetType()
                .GetMethods()
                .First(m => m.Name == "Set" && m.IsGenericMethod);

            // 调用DbSet<TEntity>方法
            var genericDbSetMethod = dbSetMethod.MakeGenericMethod(entityType);
            var dbSet = genericDbSetMethod.Invoke(_dbContext, null);

            // 获取IQueryable接口
            var queryable = (IQueryable)dbSet;

            // 应用过滤条件
            queryable = ApplyFilterConditions(queryable, entityType, input.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance), input);

            return queryable;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="searchType"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        private IQueryable BuildDynamicQuery(Type entityType, Type searchType, object input)
        {
            // 获取DbSet方法
            var dbSetMethod = _dbContext.GetType()
                .GetMethods()
                .First(m => m.Name == "Set" && m.IsGenericMethod);

            // 调用DbSet<TEntity>方法
            var genericDbSetMethod = dbSetMethod.MakeGenericMethod(entityType);
            var dbSet = genericDbSetMethod.Invoke(_dbContext, null);

            // 获取IQueryable接口
            var queryable = (IQueryable)dbSet;

            // 应用过滤条件
            queryable = ApplyFilterConditions(queryable, entityType, searchType.GetProperties(BindingFlags.Public | BindingFlags.Instance), input);

            return queryable;
        }

        /// <summary>
        /// 应用过滤条件的方法
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="properties"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        private IQueryable ApplyFilterConditions(IQueryable query, Type entityType, PropertyInfo[] properties, object input)
        {
            // 获取输入对象的所有属性
            //var properties = input.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            var ignors = new List<string> { "page", "size", "orderby" };

            foreach (var property in properties)
            {
                if (ignors.Contains(property.Name))
                {
                    continue;
                }
                // 跳过不需要作为过滤条件的属性
                //if (property.Name == "page" || property.Name == "size" || property.Name == "orderby" || property.GetValue(input) == null)
                //{
                //    continue;
                //}

                // 获取属性值
                var value = property.GetValue(input);

                if (IsDefaultValue(value, property.PropertyType))
                {
                    continue;
                }

                // 特殊处理搜索关键词
                if (property.Name == "word" && !string.IsNullOrEmpty(value?.ToString()))
                {
                    //是否要一个字段标记这个?
                    query = ApplySearchKeyword(query, entityType, value.ToString());

                    continue;
                }

                //Logger.LogInformation($"Search Property.Name: {property.Name} Type:{property.PropertyType.Name} FullName:{property.PropertyType.FullName}");

                var btype = property.PropertyType;

                if (btype == typeof(bool))
                {
                    var pro = FindSearchProperty(property, entityType);
                    if (pro != null)
                    {
                        query = ApplyComparisonFilter(query, entityType, pro, value, ReturnOperator(property));
                    }
                    continue;
                }

                if (btype == typeof(DateTime) || btype == typeof(DateTime?))
                {
                    if (property.GetCustomAttributes<PasteDaterangeAttribute>()?.Any() == true)
                    {
                        var find = property.GetCustomAttributes<PasteDaterangeAttribute>().FirstOrDefault();
                        if (find != null && find != default)
                        {
                            var edate_pro = find.Args2;
                            var sdate_str = property.GetValue(input);
                            var end_property = properties.Where(x => x.Name == edate_pro).FirstOrDefault();
                            if (end_property != null && end_property != default)
                            {
                                if (DateTime.TryParse(sdate_str.ToString(), out var sdate))
                                {
                                    var edate_str = end_property.GetValue(input);
                                    if (DateTime.TryParse(edate_str.ToString(), out var edate))
                                    {
                                        var pro = FindSearchProperty(property, entityType);
                                        if (pro != null)
                                        {
                                            query = ApplyComparisonFilter(query, entityType, pro, sdate, "LessThanOrEqual");
                                            query = ApplyComparisonFilter(query, entityType, pro, edate, "GreaterThanOrEqual");
                                        }
                                        else
                                        {
                                            Logger.LogInformation("没有在字段:{0} 中找到对应的字段 是否配置了PasteField特性 !", property.Name);
                                        }
                                    }
                                }
                            }
                            ignors.Add(edate_pro);
                        }
                    }
                    continue;
                }

                if (btype == typeof(string))
                {
                    var pro = FindSearchProperty(property, entityType);
                    if (pro != null)
                    {
                        query = ApplyComparisonFilter(query, entityType, pro, value.ToString(), ReturnOperator(property));
                    }
                    continue;
                }

                ////是否有PasteFieldAttribute特性 比如 user_id实际为UserId
                //var target_property = property.Name;
                //if (property.GetCustomAttributes<PasteFieldAttribute>()?.Any() == true)
                //{
                //    var find = property.GetCustomAttributes<PasteFieldAttribute>().FirstOrDefault();
                //    if (find != null && find != default)
                //    {
                //        target_property = find.Args1;
                //    }
                //}
                //// 检查实体是否有对应的属性
                //var entityProperty = entityType.GetProperty(target_property);
                //if (entityProperty != null && entityProperty.PropertyType == property.PropertyType)
                //{
                //    // 动态构建表达式: x => x.Property == value
                //    query = ApplyEqualsFilter(query, entityType, entityProperty, value);
                //}

            }
            return query;
        }

        /// <summary>
        /// 获取运算符
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        private string ReturnOperator(PropertyInfo property)
        {
            var finds = property.GetCustomAttributes<PasteFieldAttribute>();
            if (finds?.Any() == true)
            {
                var find = finds.FirstOrDefault();
                if (find != null && find != default)
                {
                    if (!String.IsNullOrEmpty(find.Args2))
                    {
                        return find.Args2;
                    }
                }
            }
            return "Equals";
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="property"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        private PropertyInfo FindSearchProperty(PropertyInfo property, Type entityType)
        {
            var target_property = property.Name;
            if (property.GetCustomAttributes<PasteFieldAttribute>()?.Any() == true)
            {
                var find = property.GetCustomAttributes<PasteFieldAttribute>().FirstOrDefault();
                if (find != null && find != default)
                {
                    target_property = find.Args1;
                }
            }

            // 检查实体是否有对应的属性
            var entityProperty = entityType.GetProperty(target_property);
            if (entityProperty != null)
            {
                //&& entityProperty.PropertyType == property.PropertyType 

                // 动态构建表达式: x => x.Property == value
                //query = ApplyEqualsFilter(query, entityType, entityProperty, value);
                return entityProperty;
            }
            else
            {
                //Console.WriteLine($"没有找到这个字段:{target_property} !");
            }
            return null;
        }

        /// <summary>
        /// 判断值是否为类型的默认值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsDefaultValue(object value, Type type)
        {
            if (value == null)
                return true;

            // 值类型处理
            if (type.IsValueType)
            {
                // 可空类型
                if (Nullable.GetUnderlyingType(type) != null)
                {
                    if (value == null)
                        return true;

                    // 获取基础类型
                    type = Nullable.GetUnderlyingType(type);
                }

                // 创建默认值实例
                object defaultValue = Activator.CreateInstance(type);

                // 比较值
                return value.Equals(defaultValue);
            }

            // 引用类型处理
            if (type == typeof(string))
            {
                return string.IsNullOrEmpty(value.ToString());
            }

            return false;
        }

        /// <summary>
        /// 应用等于过滤条件的方法
        /// 简单应用过滤查询
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private IQueryable ApplyEqualsFilter(IQueryable query, Type entityType, PropertyInfo property, object value)
        {
            var parameter = Expression.Parameter(entityType, "x");
            var propertyAccess = Expression.Property(parameter, property.Name);
            var constant = Expression.Constant(value);

            var equalExpression = Expression.Equal(propertyAccess, constant);
            var lambda = Expression.Lambda(equalExpression, parameter);


            var whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new Type[] { entityType },
                query.Expression,
                lambda);

            return query.Provider.CreateQuery(whereCallExpression);
        }

        /// <summary>
        /// 应用比较过滤条件(支持多种操作符)
        /// 请勿删除,是上面这个的扩展
        /// </summary>
        private IQueryable ApplyComparisonFilter(IQueryable query, Type entityType, PropertyInfo property, object value, string operatorName = "Equals")
        {
            var parameter = Expression.Parameter(entityType, "x");
            var propertyAccess = Expression.Property(parameter, property.Name);
            var constant = Expression.Constant(value, property.PropertyType);

            // 根据操作符名称构建表达式
            Expression comparisonExpression;
            switch (operatorName)
            {
                case "Equals":
                    comparisonExpression = Expression.Equal(propertyAccess, constant);
                    break;
                case "NotEquals":
                    comparisonExpression = Expression.NotEqual(propertyAccess, constant);
                    break;
                case "GreaterThan":
                    comparisonExpression = Expression.GreaterThan(propertyAccess, constant);
                    break;
                case "GreaterThanOrEqual":
                    comparisonExpression = Expression.GreaterThanOrEqual(propertyAccess, constant);
                    break;
                case "LessThan":
                    comparisonExpression = Expression.LessThan(propertyAccess, constant);
                    break;
                case "LessThanOrEqual":
                    comparisonExpression = Expression.LessThanOrEqual(propertyAccess, constant);
                    break;
                case "Contains":
                    // 处理字符串Contains
                    if (property.PropertyType == typeof(string))
                    {
                        var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                        comparisonExpression = Expression.Call(propertyAccess, containsMethod, constant);
                    }
                    else
                    {
                        // 处理集合Contains(如List<T>.Contains)
                        var containsMethod = property.PropertyType.GetMethod("Contains", new[] { property.PropertyType.GenericTypeArguments[0] });
                        comparisonExpression = Expression.Call(propertyAccess, containsMethod, constant);
                    }
                    break;
                default:
                    throw new ArgumentException($"不支持的操作符: {operatorName}");
            }

            var lambda = Expression.Lambda(comparisonExpression, parameter);
            var whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new Type[] { entityType },
                query.Expression,
                lambda);

            return query.Provider.CreateQuery(whereCallExpression);
        }

        ///// <summary>
        ///// 应用搜索关键词的方法
        ///// </summary>
        ///// <param name="query"></param>
        ///// <param name="entityType"></param>
        ///// <param name="keyword"></param>
        ///// <returns></returns>
        //private IQueryable ApplySearchKeyword(IQueryable query, Type entityType, string keyword)
        //{
        //    if (String.IsNullOrEmpty(keyword))
        //    {
        //        return query;
        //    }
        //    // 获取所有字符串类型的属性
        //    var stringProperties = entityType.GetProperties()
        //        .Where(p => p.PropertyType == typeof(string))
        //        .ToList();

        //    if (!stringProperties.Any())
        //        return query;

        //    // 构建 OR 表达式: x => x.Prop1.Contains(keyword) || x.Prop2.Contains(keyword) || ...
        //    var parameter = Expression.Parameter(entityType, "x");
        //    Expression orExpression = null;

        //    var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });

        //    foreach (var property in stringProperties)
        //    {
        //        var propertyAccess = Expression.Property(parameter, property.Name);
        //        var constant = Expression.Constant(keyword);
        //        var containsExpression = Expression.Call(propertyAccess, containsMethod, constant);

        //        if (orExpression == null)
        //            orExpression = containsExpression;
        //        else
        //            orExpression = Expression.OrElse(orExpression, containsExpression);
        //    }

        //    if (orExpression != null)
        //    {
        //        var lambda = Expression.Lambda(orExpression, parameter);

        //        var whereCallExpression = Expression.Call(
        //            typeof(Queryable),
        //            "Where",
        //            new Type[] { entityType },
        //            query.Expression,
        //            lambda);

        //        query = query.Provider.CreateQuery(whereCallExpression);
        //    }

        //    return query;
        //}

        /// <summary>
        /// 应用关键字搜索
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="keyword"></param>
        /// <returns></returns>
        private IQueryable ApplySearchKeyword(IQueryable query, Type entityType, string keyword)
        {
            // 外部已确保keyword非空,这里仅做防御性校验
            if (string.IsNullOrEmpty(keyword))
            {
                return query;
            }

            var stringProperties = entityType.GetProperties()
                .Where(p => p.PropertyType == typeof(string) && p.GetCustomAttributes<PasteSearchAttribute>()?.Any() == true)
                .ToList();

            if (!stringProperties.Any())
            {
                return query;
            }

            var parameter = Expression.Parameter(entityType, "x");
            Expression orExpression = null;
            var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });

            foreach (var property in stringProperties)
            {
                // 只构建“属性包含关键词”的表达式,不添加任何与关键词为空相关的判断
                var propertyAccess = Expression.Property(parameter, property);
                var containsExpression = Expression.Call(
                    propertyAccess,
                    containsMethod,
                    Expression.Constant(keyword) // 直接使用关键词“bb”
                );

                orExpression = orExpression == null
                    ? containsExpression
                    : Expression.OrElse(orExpression, containsExpression);
            }

            var lambda = Expression.Lambda(orExpression, parameter);
            var whereCall = Expression.Call(
                typeof(Queryable),
                "Where",
                new[] { entityType },
                query.Expression,
                lambda
            );

            return query.Provider.CreateQuery(whereCall);
        }

        /// <summary>
        /// 计算 page  size  orderby
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private IQueryable ApplyPagingAndSorting(IQueryable query, Type entityType, InputSearchBase input)
        {
            // 获取Id属性信息
            var idProperty = entityType.GetProperty("Id");
            if (idProperty == null)
            {
                throw new PasteCodeException($"实体 {entityType.Name} 不包含Id属性", 500);
            }

            // 构建排序表达式
            var parameter = Expression.Parameter(entityType, "x");
            var propertyAccess = Expression.Property(parameter, idProperty);
            var lambda = Expression.Lambda(propertyAccess, parameter);

            // 使用正确的属性类型作为排序键类型
            var orderByDescendingCall = Expression.Call(
                typeof(Queryable),
                "OrderByDescending",
                new Type[] { entityType, idProperty.PropertyType }, // 使用实际的属性类型
                query.Expression,
                lambda);

            query = query.Provider.CreateQuery(orderByDescendingCall);

            // 应用分页
            query = query.Skip((input.page - 1) * input.size).Take(input.size);

            return query;
        }


        /// <summary>
        /// 上面的补充,用于其他查询
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="searchType"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private IQueryable ApplyPagingAndSorting(IQueryable query, Type entityType, Type searchType, Object input)
        {
            // 获取Id属性信息
            var idProperty = entityType.GetProperty("Id");
            if (idProperty == null)
            {
                throw new PasteCodeException($"实体 {entityType.Name} 不包含Id属性", 500);
            }

            var page = 1;
            var size = 20;
            var orderby = String.Empty;

            foreach (var ii in searchType.GetProperties())
            {
                if (string.Equals(ii.Name, "page", StringComparison.CurrentCultureIgnoreCase))
                {
                    var _page = ii.GetValue(input);
                    int.TryParse(_page.ToString(), out page);
                    continue;
                }
                if (string.Equals(ii.Name, "size", StringComparison.CurrentCultureIgnoreCase))
                {
                    var _page = ii.GetValue(input);
                    int.TryParse(_page.ToString(), out size);
                    continue;
                }
                if (string.Equals(ii.Name, "orderby", StringComparison.CurrentCultureIgnoreCase))
                {
                    var _page = ii.GetValue(input);
                    orderby = _page.ToString().Trim();
                    continue;
                }
            }

            if (!String.IsNullOrEmpty(orderby))
            {
                query = query.OrderBy(orderby);
            }
            else
            {
                // 构建排序表达式 默认 OrderByDescending(x=>x.Id)
                var parameter = Expression.Parameter(entityType, "x");
                var propertyAccess = Expression.Property(parameter, idProperty);
                var lambda = Expression.Lambda(propertyAccess, parameter);

                // 使用正确的属性类型作为排序键类型
                var orderByDescendingCall = Expression.Call(
                    typeof(Queryable),
                    "OrderByDescending",
                    new Type[] { entityType, idProperty.PropertyType }, // 使用实际的属性类型
                    query.Expression,
                    lambda);

                query = query.Provider.CreateQuery(orderByDescendingCall);
            }
            // 应用分页
            query = query.Skip((page - 1) * size).Take(size);

            return query;
        }

        /// <summary>
        /// 执行计数查询的方法
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        private async Task<int> ExecuteCountQuery(IQueryable query, Type entityType)
        {
            var countMethod = typeof(Queryable)
                .GetMethods()
                .First(m => m.Name == "Count" && m.GetParameters().Length == 1)
                .MakeGenericMethod(entityType);

            return (int)await Task.FromResult(countMethod.Invoke(null, new object[] { query }));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private async Task<List<object>> ExecuteQuery(IQueryable query, Type entityType)
        {
            try
            {
                // 获取 EntityFrameworkQueryableExtensions 类型
                var extensionsType = typeof(EntityFrameworkQueryableExtensions);

                // 查找 ToListAsync 方法,匹配名称、泛型和参数
                var toListMethod = extensionsType.GetMethods(BindingFlags.Static | BindingFlags.Public)
                    .First(m =>
                        m.Name == "ToListAsync" &&
                        m.IsGenericMethodDefinition &&
                        m.GetParameters().Length == 2 &&  // 注意:有两个参数(查询和 CancellationToken)
                        m.GetParameters()[0].ParameterType == typeof(IQueryable<>).MakeGenericType(m.GetGenericArguments()[0]) &&
                        m.GetParameters()[1].ParameterType == typeof(CancellationToken));

                // 构建泛型方法
                var genericToListMethod = toListMethod.MakeGenericMethod(entityType);

                // 调用方法,传入 CancellationToken.None
                var task = (Task)genericToListMethod.Invoke(null, new object[] { query, CancellationToken.None });
                await task;

                // 获取结果
                var resultProperty = task.GetType().GetProperty("Result");
                var entities = (IEnumerable)resultProperty.GetValue(task);

                return entities.Cast<object>().ToList();
            }
            catch (Exception ex)
            {
                throw new PasteCodeException($"执行查询时发生错误: {ex.Message}", 500);
            }
        }

        /// <summary>
        /// 映射实体到DTO的方法
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="entityType"></param>
        /// <param name="dtoType"></param>
        /// <returns></returns>
        private List<object> MapEntitiesToDtos(List<object> entities, Type entityType, Type dtoType)
        {
            var result = new List<object>();

            foreach (var entity in entities)
            {
                var dto = Activator.CreateInstance(dtoType);

                // 获取DTO类型的所有可写属性
                var dtoProperties = dtoType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Where(p => p.CanWrite);

                foreach (var dtoProperty in dtoProperties)
                {
                    // 查找实体中对应的属性
                    var entityProperty = entityType.GetProperty(dtoProperty.Name);

                    // 如果属性名称和类型都匹配,则复制值
                    if (entityProperty != null && entityProperty.PropertyType == dtoProperty.PropertyType)
                    {
                        var value = entityProperty.GetValue(entity);
                        dtoProperty.SetValue(dto, value);
                    }
                }
                result.Add(dto);
            }
            return result;
        }
        // 类型缓存
        //private readonly ConcurrentDictionary<string, Type> _typeCache = new ConcurrentDictionary<string, Type>();
        #endregion

        #region 

        /// <summary>
        /// 动态构建Select表达式,将实体投影到DTO
        /// </summary>
        private Expression<Func<object, object>> BuildSelectExpressionV1(Type entityType, Type dtoType)
        {
            var parameter = Expression.Parameter(typeof(object), "x");
            var convertedParameter = Expression.Convert(parameter, entityType);

            // 创建DTO构造表达式
            var dtoNewExpression = Expression.New(dtoType);

            // 构建属性赋值绑定
            var bindings = new List<MemberBinding>();
            foreach (var dtoProperty in dtoType.GetProperties())
            {
                // 查找实体中对应的属性
                var entityProperty = entityType.GetProperty(dtoProperty.Name);

                // 如果属性名称和类型都匹配,则添加到绑定
                if (entityProperty != null && entityProperty.PropertyType == dtoProperty.PropertyType)
                {
                    var propertyAccess = Expression.Property(convertedParameter, entityProperty);
                    bindings.Add(Expression.Bind(dtoProperty, propertyAccess));
                }
            }

            // 创建初始化器表达式
            var initExpression = Expression.MemberInit(dtoNewExpression, bindings);

            // 转换为object类型
            var convertExpression = Expression.Convert(initExpression, typeof(object));

            // 创建lambda表达式
            return Expression.Lambda<Func<object, object>>(convertExpression, parameter);
        }

        //private LambdaExpression BuildSelectExpression(Type entityType, Type dtoType)
        //{
        //    // 创建参数表达式 (x => ...)
        //    var parameter = Expression.Parameter(entityType, "x");

        //    // 创建DTO属性的绑定
        //    var bindings = dtoType.GetProperties()
        //        .Where(p => p.CanWrite)
        //        .Select(p =>
        //        {
        //            // 查找实体类型中是否有同名属性
        //            var entityProperty = entityType.GetProperty(p.Name);
        //            if (entityProperty != null && entityProperty.CanRead)
        //            {
        //                // 创建属性访问表达式 x.Property
        //                var propertyAccess = Expression.Property(parameter, entityProperty);

        //                // 如果需要类型转换,添加Convert操作
        //                if (p.PropertyType != entityProperty.PropertyType)
        //                {
        //                    propertyAccess = Expression.Convert(propertyAccess, p.PropertyType);
        //                }

        //                return Expression.Bind(p, propertyAccess);
        //            }

        //            return null;
        //        })
        //        .Where(b => b != null)
        //        .ToList();

        //    // 创建DTO对象初始化表达式
        //    var dtoInit = Expression.MemberInit(
        //        Expression.New(dtoType),
        //        bindings);

        //    // 创建lambda表达式 x => new Dto { ... }
        //    return Expression.Lambda(dtoInit, parameter);
        //}

        /// <summary>
        /// 直接查询并投影为DTO
        /// </summary>
        private async Task<List<object>> ExecuteProjectionQuery(IQueryable query, Type entityType, Type dtoType)
        {
            try
            {

                // 构建Select表达式
                var selectExpression = BuildSelectExpression(entityType, dtoType);

                // 创建泛型Func类型 (EntityType -> DtoType)
                var funcType = typeof(Func<,>).MakeGenericType(entityType, dtoType);

                // 创建lambda表达式
                var lambda = Expression.Lambda(funcType, selectExpression.Body, selectExpression.Parameters[0]);

                // 构建Select方法
                var selectMethod = typeof(Queryable).GetMethods()
                    .First(m => m.Name == "Select" && m.GetParameters().Length == 2)
                    .MakeGenericMethod(entityType, dtoType);

                // 应用Select投影
                var projectedQuery = selectMethod.Invoke(null, new object[] { query, lambda });

                var toListMethod = typeof(EntityFrameworkQueryableExtensions).GetMethods()
                    .First(m => m.Name == "ToListAsync" && m.GetParameters().Length == 2)
                    .MakeGenericMethod(typeof(object));
                //Console.WriteLine("line 1640");
                var task = (Task)toListMethod.Invoke(null, new object[] { projectedQuery, CancellationToken.None });
                await task;
                //Console.WriteLine("line 1643");
                var resultProperty = task.GetType().GetProperty("Result");
                return (List<object>)resultProperty.GetValue(task);

            }
            catch (Exception ex)
            {
                throw new PasteCodeException($"执行投影查询时发生错误: {ex.Message}", 500);
            }
        }

        private LambdaExpression BuildSelectExpression(Type entityType, Type dtoType)
        {
            // 创建参数表达式 (x => ...)
            var parameter = Expression.Parameter(entityType, "x");

            // 创建DTO属性的绑定
            var bindings = dtoType.GetProperties()
                .Where(p => p.CanWrite)
                .Select(p =>
                {
                    // 查找实体类型中是否有同名属性
                    var entityProperty = entityType.GetProperty(p.Name);
                    if (entityProperty != null && entityProperty.CanRead)
                    {
                        // 创建属性访问表达式 x.Property
                        var propertyAccess = Expression.Property(parameter, entityProperty);

                        // 如果需要类型转换,添加Convert操作
                        //if (p.PropertyType != entityProperty.PropertyType)
                        //{
                        //    propertyAccess = Expression.Convert(propertyAccess, p.PropertyType);
                        //}

                        return Expression.Bind(p, propertyAccess);
                    }

                    return null;
                })
                .Where(b => b != null)
                .ToList();

            // 创建DTO对象初始化表达式
            var dtoInit = Expression.MemberInit(
                Expression.New(dtoType),
                bindings);

            // 创建lambda表达式 x => new Dto { ... }
            return Expression.Lambda(dtoInit, parameter);
        }

        /// <summary>
        /// 构建ID查询条件
        /// </summary>
        private IQueryable BuildIdQuery(Type entityType, HashSet<object> ids)
        {
            // 获取DbSet
            var dbSetMethod = _dbContext.GetType()
                .GetMethods()
                .First(m => m.Name == "Set" && m.IsGenericMethod);
            var genericDbSetMethod = dbSetMethod.MakeGenericMethod(entityType);
            var dbSet = genericDbSetMethod.Invoke(_dbContext, null);
            var queryable = (IQueryable)dbSet;

            //if (ids.Count == 0)
            //{
            //    return queryable.Where(x => false); // 返回空结果
            //}

            // 动态构建ID查询表达式: x => ids.Contains(x.Id)
            var parameter = Expression.Parameter(entityType, "x");
            var idProperty = entityType.GetProperty("Id");
            var propertyAccess = Expression.Property(parameter, idProperty);

            // 创建包含所有ID的常量表达式
            var method = typeof(Enumerable).GetMethods()
                .First(m => m.Name == "Contains" && m.GetParameters().Length == 2)
                .MakeGenericMethod(idProperty.PropertyType);

            var constant = Expression.Constant(ids);
            var containsExpression = Expression.Call(method, constant, propertyAccess);

            var lambda = Expression.Lambda(containsExpression, parameter);
            var whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new Type[] { entityType },
                queryable.Expression,
                lambda);

            return queryable.Provider.CreateQuery(whereCallExpression);
        }


        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityType"></param>
        /// <returns></returns>
        private object GetDbSet(Type entityType)
        {
            var dbSetMethod = _dbContext.GetType()
                .GetMethods()
                .First(m => m.Name == "Set" && m.IsGenericMethod);

            return dbSetMethod.MakeGenericMethod(entityType).Invoke(_dbContext, null);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private object GetPropertyValue(object obj, string propertyName)
        {
            var property = obj.GetType().GetProperty(propertyName);
            return property?.GetValue(obj);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        private void SetPropertyValue(object obj, string propertyName, object value)
        {
            var property = obj.GetType().GetProperty(propertyName);
            if (property != null && property.CanWrite)
            {
                // 处理类型转换
                if (value != null && property.PropertyType != value.GetType())
                {
                    value = Convert.ChangeType(value, property.PropertyType);
                }

                property.SetValue(obj, value);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        /// <param name="sourceType"></param>
        /// <param name="destinationType"></param>
        private void MapProperties(object source, object destination, Type sourceType, Type destinationType)
        {
            // 获取源类型的所有可读属性
            var sourceProperties = sourceType.GetProperties()
                .Where(p => p.CanRead)
                .ToList();

            // 获取目标类型的所有可写属性
            var destinationProperties = destinationType.GetProperties()
                .Where(p => p.CanWrite)
                .ToList();

            // 映射相同名称和类型的属性
            foreach (var sourceProperty in sourceProperties)
            {
                var destinationProperty = destinationProperties
                    .FirstOrDefault(p => p.Name == sourceProperty.Name && p.PropertyType == sourceProperty.PropertyType);

                if (destinationProperty != null)
                {
                    var value = sourceProperty.GetValue(source);
                    destinationProperty.SetValue(destination, value);
                }
            }
        }


        #endregion

    }

}

有几个注意要点

1.所有的Dto查询等要放在同一个项目,
也就是XXX.Application.Contracts下面,
关键点和InputSearchBase放一个项目,
你看代码会发现查找反射的时候是基于这个查找的

2.如果你的项目没有UserInfo这个Entity,
则替换成一个基础的就行,原理和上面的一样,
为了在程序集按照名称查找!

3.如果你某一个Entity要实现自己的逻辑,
你按照代码生成即可,因为默认的路由权重比较高,会覆盖这个!

4.基于上面的信息,XXX.Domain/template/config.json下面多了一个配置
“create_appservice”: true,//是否创建对应的AppService

5.恭喜你,你得项目管理端非常干净了,真的非常干净,可以做到管理端页面不超过10个,而管理端的接口不多于2个!!!
当然了,如果你有比较特殊的需求除外哈!

6.记住PasteForm的宗旨是,Dto驱动管理端,所以至于业务端等是原来怎么写就怎么写!
甚至我觉得用户端的有些表单也可以用这个思路来开发!
因为他高效,简洁!特备适合频繁变更需求的,所见即所得!

超级管理员
立即前往参与当前项目管理 说明
贴代码框架
贴代码框架PasteForm的在线文档,主要介绍理念和特性及实际案例!
贴代码文档
什么才叫操作文档?对于操作人员来说,遇到哪个字段不懂意思,点击下即可查阅说明,这就是最好的文档!
PasteSpider在线操作文档
PasteSpider是专门为开发者开发的部署工具,五分钟上手,小内存服务器也可以使用,使用旁载模式,运行更安全!!!目前仅支持linux的服务器,win服务器的版本将在不久到来!
贴代码在线客服文档
是客服系统也是营销系统,支持丰富的话术配置,支持自定义消息格式,支持多站点入驻模式,一键部署快速搭建!
当前项目开源地址:PasteDocument在线文档,哪里不会点哪里