文件内容 PasteDefaultHelper.cs 110 KB 107810 字符
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using PasteApeart.Application.Contracts;
using PasteApeart.Helper;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;

namespace PasteApeart.Application
{
    /// <summary>
    /// 通用接口帮助类
    /// </summary>
    public class PasteDefaultHelper : IPasteDefaultHelper
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly IMemoryCache _memoryCache;

        /// <summary>
        ///  typeof(InputSearchBase).Assembly.GetTypes();
        /// </summary>
        private readonly Type[] _dtoTypes;

        /// <summary>
        /// typeof(RoleInfo).Assembly.GetTypes();
        /// </summary>
        private readonly Type[] _entityTypes;

        /// <summary>
        /// LinqExtend的Type
        /// </summary>
        private readonly Type _linqExtendType;

        ///// <summary>
        ///// <![CDATA[services.AddSingleton(sp => new PasteApeartDefaultHelper(sp.GetRequiredService<IMemoryCache>(),() => typeof(RoleInfo).Assembly.GetTypes()))]]>
        ///// </summary>
        ///// <param name="memoryCache"></param>
        ///// <param name="typeDomainScanner"></param>
        ///// <param name="typeDtoScanner"></param>
        ///// <param name="extendType"></param>
        //public PasteDefaultHelper(IMemoryCache memoryCache, Func<Type[]> typeDomainScanner, Func<Type[]> typeDtoScanner, Type extendType)
        //{
        //    _memoryCache = memoryCache;
        //    _domainTypeScanner = typeDomainScanner;
        //    _dtoTypeScanner = typeDtoScanner;
        //    _linqExtendType = extendType;
        //}

        /// <summary>
        /// <![CDATA[services.AddSingleton(sp => new PasteApeartDefaultHelper(sp.GetRequiredService<IMemoryCache>(),() => typeof(RoleInfo).Assembly.GetTypes()))]]>
        /// </summary>
        /// <param name="memoryCache"></param>
        /// <param name="typeDomainScanner"></param>
        /// <param name="typeDtoScanner"></param>
        /// <param name="extendType"></param>
        public PasteDefaultHelper(IMemoryCache memoryCache, Type[] typeDomainScanner, Type[] typeDtoScanner, Type extendType)
        {
            _memoryCache = memoryCache;
            _entityTypes = typeDomainScanner;
            _dtoTypes = typeDtoScanner;
            _linqExtendType = extendType;
        }

        /// <summary>
        /// 等效于 ReadTypeProperties
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private PropertyInfo[] MemoryProperties(Type t)
        {
            return ReadTypeProperties(t);
        }

        /// <summary>
        /// 获取某一个字段的PropertyInfo信息 可能返回null
        /// </summary>
        /// <param name="t"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private PropertyInfo MemoryPropertyInfo(Type t, string propertyName)
        {
            var types = MemoryProperties(t);
            if (types != null)
            {
                return types.Where(x => x.Name == propertyName).FirstOrDefault();
            }
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private Type FindDomainTypeThrowException(string entityName)
        {
            var type = FindOnlyDomainType(entityName);
            if (type == null)
            {
                throw new PasteCodeException($"没有在项目Domain中找到:{entityName} ");
            }
            return type;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        private Type FindOnlyDomainType(string entityName)
        {
            var domainTypeKey = $"domain.type.name.{entityName}";
            return _memoryCache.GetOrCreate(domainTypeKey, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(500);
                var types = ListDomainTypes();
                return types?.FirstOrDefault(t =>
                    string.Equals(t.Name, entityName, StringComparison.OrdinalIgnoreCase)
                );
            });

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private Type FindDtoTypeThrowException(string entityName)
        {
            var type = FindOnlyDtoType(entityName);
            if (type == null)
            {
                throw new PasteCodeException($"没有在程序集:{nameof(InputSearchBase)} 中找到:{entityName} ");
            }
            return type;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dtoName"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private Type FindOnlyDtoType(string dtoName)
        {
            if (dtoName == nameof(InputSearchBase))
            {
                return typeof(InputSearchBase);
            }
            var domainTypeKey = $"dto.type.name.{dtoName}";
            return _memoryCache.GetOrCreate(domainTypeKey, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(500);
                var types = ListDtoTypes();
                return types?.FirstOrDefault(t =>
                    string.Equals(t.Name, dtoName, StringComparison.OrdinalIgnoreCase)
                );
            });
        }



        /// <summary>
        /// 不要调用
        /// </summary>
        /// <returns></returns>
        private Type[] ListDomainTypes()
        {
            //return _memoryCache.GetOrCreate("domain.types", entry =>
            //{
            //    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(450);
            //    //return typeof(RoleInfo).Assembly.GetTypes(); // 耗时的程序集扫描
            //    return _entityTypes();
            //});
            return _entityTypes;
        }



        /// <summary>
        /// 不要调用
        /// </summary>
        /// <returns></returns>
        private Type[] ListDtoTypes()
        {
            //return _memoryCache.GetOrCreate("dto.types", entry =>
            //{
            //    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(450);
            //    //return typeof(InputSearchBase).Assembly.GetTypes(); // 耗时的程序集扫描
            //    return _dtoTypes();
            //});
            return _dtoTypes;
        }

        /// <summary>
        /// 扩展 ExtendBind的赋值 查询某一个对象,有多少绑定,比如给角色绑定权限,给用户绑定角色
        /// </summary>
        /// <param name="listDtoType"></param>
        /// <param name="_dbContext"></param>
        /// <param name="dataList"></param>
        /// <param name="searchType"></param>
        /// <param name="searchModel"></param>
        public async Task ReadExtendBind(DbContext _dbContext, Type listDtoType, List<object> dataList, Type searchType, object searchModel)
        {
            var extendBindProperty = MemoryPropertyInfo(listDtoType, "ExtendBind");// listDtoType.GetProperty("ExtendBind");
            if (extendBindProperty == null)
            {
                return;
            }
            //var find_extend_bind = searchType.GetProperties().Where(x=>x.Attributes)
            var properties = MemoryProperties(searchType).Where(p => p.GetCustomAttributes(typeof(PasteExtendBindAttribute), true).Length > 0).ToList();
            if (properties?.Any() == false)
            {
                //Logger.LogError($"没有在:{searchType.Name} 找到具有PasteExtendBindAttribute的字段");
                return;
            }

            foreach (var extendProperty in properties)
            {
                //UserId  GradeId
                var extendGradeId = extendProperty.GetValue(searchModel);
                if (extendGradeId == null)
                {
                    //Logger.LogWarning($"{searchType.Name}.{extendProperty.Name}的值为null,不需要查询");
                    continue;
                }

                var gradeIdString = extendGradeId.ToString();
                if (gradeIdString == "0" || String.IsNullOrEmpty(gradeIdString))
                {
                    //Logger.LogWarning($"{searchType.Name}.{extendProperty.Name}的值为{gradeIdString},不需要查询");
                    continue;
                }

                var gradeIdValue = Convert.ChangeType(gradeIdString, extendProperty.PropertyType);

                var attr = extendProperty.GetCustomAttribute<PasteExtendBindAttribute>();

                var bindEntityType = FindEntityType(attr.Args1);

                var dbSet = FindDbSetObject(_dbContext, bindEntityType);

                //var dbSet = dbSetProperty.GetValue(_dbContext);
                var whereMethod = typeof(Queryable).GetMethods()
                    .First(m => m.Name == "Where" && m.GetParameters().Length == 2)
                    .MakeGenericMethod(dbSet.GetType().GenericTypeArguments[0]);

                // 创建 lambda 参数和表达式
                var parameter = Expression.Parameter(dbSet.GetType().GenericTypeArguments[0], "x");
                var property = Expression.Property(parameter, attr.Args3);
                var constant = Expression.Constant(gradeIdValue);
                var equal = Expression.Equal(property, constant);
                var lambda = Expression.Lambda(equal, parameter);

                // 执行 Where 方法
                var filteredQuery = whereMethod.Invoke(null, new object[] { dbSet, lambda });

                var roleIdPropertyType = MemoryPropertyInfo(bindEntityType, attr.Args2).PropertyType;// bindEntityType.GetProperty(attr.Args2).PropertyType;
                                                                                                     // 执行 Select 方法获取 RoleId
                var selectMethod = typeof(Queryable).GetMethods()
                    .First(m => m.Name == "Select" && m.GetParameters().Length == 2)
                    .MakeGenericMethod(
                        dbSet.GetType().GenericTypeArguments[0],
                        roleIdPropertyType);

                // 创建 Select lambda
                var selectParameter = Expression.Parameter(dbSet.GetType().GenericTypeArguments[0], "x");
                var selectProperty = Expression.Property(selectParameter, attr.Args2);
                var selectLambda = Expression.Lambda(selectProperty, selectParameter);

                var projectedQuery = selectMethod.Invoke(null, new object[] { filteredQuery, selectLambda });
                //var bindIdProperty = bindEntityType.GetProperty("Id", BindingFlags.Public | BindingFlags.Instance);
                var bindIdProperty = ReadCurrentPropertyThrowException(bindEntityType, attr.Args2);
                var extensionsType = typeof(EntityFrameworkQueryableExtensions);
                // 查找 ToListAsync 方法,匹配名称、泛型和参数
                var toListMethod = extensionsType.GetMethods(BindingFlags.Static | BindingFlags.Public)
                    .First(m =>
                        m.Name == "ToArrayAsync" &&
                        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(bindIdProperty.PropertyType);
                // 调用方法,传入 CancellationToken.None
                var task = (Task)genericToListMethod.Invoke(null, new object[] { projectedQuery, CancellationToken.None });
                await task;

                // 获取结果
                var resultProperty = task.GetType().GetProperty("Result");
                var entities = (IEnumerable)resultProperty.GetValue(task);
                var binds = entities.Cast<object>().ToList();

                if (binds != null && binds.Count > 0)
                {
                    var idProperty = ReadCurrentProperty(listDtoType, "Id");
                    if (idProperty != null && extendBindProperty != null &&
                        extendBindProperty.PropertyType == typeof(bool))
                    {
                        var ids = new List<string>();//转string因为Id可能是guid int long string 等
                        foreach (var bind in binds)
                        {
                            ids.Add(bind.ToString());
                        }
                        foreach (var item in dataList)
                        {
                            var idValue = idProperty.GetValue(item);
                            if (idValue != null)
                            {
                                if (ids.Contains(idValue.ToString()))
                                {
                                    extendBindProperty.SetValue(item, true);
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 处理映射对象 搜索的信息检索
        /// 处理基础查询page size word等信息,如果有其他的则进行转化,由queryString转化成SearchObject
        /// </summary>
        /// <param name="_search"></param>
        /// <param name="searchType"></param>
        /// <param name="search"></param>
        /// <returns></returns>
        public InputSearchBase MapperToQueryModel(string _search, Type searchType, object search)
        {

            var info = new InputSearchBase();

            if (!String.IsNullOrEmpty(_search))
            {
                if (_search.StartsWith("?"))
                {
                    _search = _search.Substring(1);
                }
                if (!String.IsNullOrEmpty(_search))
                {
                    var _dic = new Dictionary<string, object>();
                    var splits = _search.Split('&');
                    foreach (var _one in splits)
                    {
                        if (_one.Contains("="))
                        {
                            var ones = _one.Split('=');
                            var _key = ones[0];
                            var _val = ones[1];
                            if (String.IsNullOrEmpty(_val))
                            {
                                continue;
                            }
                            if (_val.Length > 1)
                            {
                                _val = HttpUtility.UrlDecode(_val);//转义 解码
                            }
                            if (!_dic.ContainsKey(_key))
                            {
                                _dic.Add(_key, _val);
                            }
                            else
                            {
                                var old_val = _dic[_key];
                                if (old_val.GetType() == typeof(List<object>))
                                {
                                    ((List<object>)old_val).Add(_val);
                                }
                                else
                                {
                                    var objs = new List<object> { old_val };
                                    objs.Add(_val);
                                    _dic[_key] = objs;
                                }
                            }
                        }
                    }
                    var pros = MemoryProperties(searchType);// searchType.GetProperties();
                    foreach (var key in _dic.Keys)
                    {
                        var val = _dic[key];
                        if (String.IsNullOrEmpty(val.ToString()))
                        {
                            continue;
                        }
                        var pro = pros.Where(x => String.Equals(x.Name, key, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                        if (pro != null)
                        {
                            if (pro.PropertyType == typeof(bool))
                            {
                                switch (val.ToString())
                                {
                                    case "1":
                                    case "true":
                                    case "True":
                                    case "on":
                                        {
                                            pro.SetValue(search, true);
                                        }
                                        break;
                                    default:
                                        pro.SetValue(search, false);
                                        break;
                                }
                                continue;
                            }
                            if (pro.PropertyType == typeof(DateTime))
                            {
                                if (DateTime.TryParse(val.ToString(), out var _dt))
                                {
                                    pro.SetValue(search, _dt);
                                }
                                continue;
                            }
                            if (pro.PropertyType == typeof(DateTime?))
                            {
                                if (DateTime.TryParse(val.ToString(), out var _dt))
                                {
                                    pro.SetValue(search, _dt);
                                }
                                continue;
                            }
                            // 处理枚举数组类型
                            if (pro.PropertyType.IsArray)
                            {
                                if (pro.PropertyType.GetElementType().IsEnum)
                                {
                                    var elementType = pro.PropertyType.GetElementType();
                                    if (val is List<object> listVal)
                                    {
                                        var enumArray = Array.CreateInstance(elementType, listVal.Count);
                                        for (int i = 0; i < listVal.Count; i++)
                                        {
                                            try
                                            {
                                                var enumValue = Enum.Parse(elementType, listVal[i].ToString(), true);
                                                enumArray.SetValue(enumValue, i);
                                            }
                                            catch
                                            {
                                                if (int.TryParse(listVal[i].ToString(), out int numericValue))
                                                {
                                                    enumArray.SetValue(Enum.ToObject(elementType, numericValue), i);
                                                }
                                            }
                                        }
                                        pro.SetValue(search, enumArray);
                                    }
                                    else
                                    {
                                        var enumArray = Array.CreateInstance(elementType, 1);
                                        try
                                        {
                                            var enumValue = Enum.Parse(elementType, val.ToString(), true);
                                            enumArray.SetValue(enumValue, 0);
                                        }
                                        catch
                                        {
                                            if (int.TryParse(val.ToString(), out int numericValue))
                                            {
                                                enumArray.SetValue(Enum.ToObject(elementType, numericValue), 0);
                                            }
                                        }
                                        pro.SetValue(search, enumArray);
                                    }
                                    continue;
                                }
                                else
                                {
                                    //Console.WriteLine($"IsArray {pro.Name} {pro.PropertyType.Name} {pro.PropertyType.GetElementType().Name}");
                                    var elementType = pro.PropertyType.GetElementType();
                                    if (val is List<object> listVal)
                                    {
                                        var enumArray = Array.CreateInstance(elementType, listVal.Count);
                                        for (int i = 0; i < listVal.Count; i++)
                                        {
                                            var enumValue = Convert.ChangeType(listVal[i].ToString(), elementType);
                                            enumArray.SetValue(enumValue, i);
                                        }
                                        pro.SetValue(search, enumArray);
                                    }
                                    else
                                    {
                                        var enumArray = Array.CreateInstance(elementType, 1);

                                        var enumValue = Convert.ChangeType(val.ToString(), elementType);
                                        enumArray.SetValue(enumValue, 0);

                                        pro.SetValue(search, enumArray);
                                    }
                                    continue;
                                }
                            }

                            // 处理普通枚举类型
                            if (pro.PropertyType.IsEnum)
                            {
                                var enumValue = Enum.Parse(pro.PropertyType, val.ToString(), true);
                                pro.SetValue(search, enumValue);
                                continue;
                            }
                            //其他类型默认转化
                            var changeValue = Convert.ChangeType(val.ToString(), pro.PropertyType);
                            pro.SetValue(search, changeValue);
                        }
                    }
                }
            }

            //page字段恒为int类型
            var pro_page = ReadCurrentProperty(searchType, "page");
            if (pro_page != null)
            {
                var page = pro_page.GetValue(search, null);
                info.page = (int)page;
            }

            var pro_size = ReadCurrentProperty(searchType, "size");
            if (pro_size != null)
            {
                var page = pro_size.GetValue(search, null);
                info.size = (int)page;
            }

            var pro_word = ReadCurrentProperty(searchType, "word");
            if (pro_word != null)
            {
                var word = pro_page.GetValue(search, null);
                if (word != null)
                {
                    if (!String.IsNullOrEmpty(word.ToString()))
                    {
                        info.word = word.ToString();
                    }
                }
            }

            return info;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_dbContext"></param>
        /// <param name="dto"></param>
        /// <param name="dtoType"></param>
        /// <returns></returns>
        public async Task BuildOuterQuery(DbContext _dbContext, object dto, Type dtoType)
        {
            #region 看看是否要执行外表查询
            foreach (var aty in MemoryProperties(dtoType))
            {
                //var _type = aty.PropertyType;
                var attributes = aty.GetCustomAttributes<PasteShortAttribute>();
                if (attributes?.Any() == true)
                {
                    var shortAttr = attributes.FirstOrDefault();
                    if (shortAttr != null && shortAttr != 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 = ReadCurrentProperty(dtoType, shortAttr.Args2);

                        if (relatedEntityType == null || targetProperty == null)
                        {
                            continue;
                        }
                        //try
                        //{
                        var dbSet = FindDbSetObject(_dbContext, relatedEntityType);
                        // 动态调用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 = _linqExtendType.GetMethod(shortAttr.Args3.Replace("()", ""), new[] { relatedEntityType });
                                // 处理特殊转换方法(例如:ToShortUser())
                                if (extend != null)
                                {
                                    //convertedResult = ConvertEntity(relatedEntity, relatedEntityType, shortAttr.Args3);
                                    convertedResult = extend.Invoke(null, new object[] { relatedEntity });
                                }
                                else
                                {
                                    convertedResult = relatedEntity;
                                    Serilog.Log.Warning($"没有找到{shortAttr.Args1} 的扩展:{shortAttr.Args3} !");
                                    continue;
                                }
                            }
                            else
                            {
                                // 默认转换:直接使用目标属性类型
                                convertedResult = relatedEntity;
                            }

                            // 设置目标属性的值
                            targetProperty.SetValue(dto, convertedResult);
                        }
                    }
                }
            }

            #endregion
        }

        /// <summary>
        /// 查询某一个数据对象 用于创建或者更新后返回ListDto使用
        /// 这个一般是给系统的其他AppService使用,比如UserInfo的创建后调用
        /// </summary>
        /// <param name="_dbContext"></param>
        /// <param name="entityName"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        public async Task<object> ReadSingleListDtoByIdAsync(DbContext _dbContext, string entityName, object id)
        {

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

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

            // 2. 动态查询实体
            var entity = await FindEntityByIdAsync(_dbContext, entityType, id);
            if (entity == null)
            {
                return null;//throw new PasteCodeException("查询的信息不存在,无法执行编辑操作!");
            }
            // 3. 动态映射实体到 DTO
            //var dto = MapEntityToDto(null, entity, entityType, dtoType);
            var dto = Activator.CreateInstance(dtoType);
            MapProperties(entity, dto, entityType, dtoType);

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

        }


        /// <summary>
        /// 查找Entity类型,和RoleInfo放一起
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        public Type FindEntityType(string entityName)
        {
            return FindDomainTypeThrowException(entityName);
        }

        /// <summary>
        /// 查找Dto的类型
        /// </summary>
        /// <param name="entityName"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public Type FindDtoType(string entityName, string suffix)
        {
            //var pascalCaseName = ConvertToPascalCase(entityName);
            var dtoName = $"{entityName}{suffix}";
            return this.FindDtoTypeThrowException(dtoName);
        }

        /// <summary>
        /// 基于名称大小写查找字段
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        public PropertyInfo GetPropertyThrowException(Type entityType, string propertyName)
        {
            //var pauseName = ConvertToPascalCase(propertyName);
            var property = MemoryProperties(entityType).Where(x => string.Equals(x.Name, propertyName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
            if (property == null || property == default)
            {
                throw new PasteCodeException("没有找到需要变更的字段!");
            }
            return property;
        }

        /// <summary>
        /// 从Domain或者Dto中查找类型
        /// </summary>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public Type AutoFindType(string typeName)
        {
            if (typeName == nameof(InputSearchBase))
            {
                return typeof(InputSearchBase);
            }
            var find = FindOnlyDtoType(typeName);
            if (find != null)
            {
                return find;
            }
            find = FindOnlyDomainType(typeName);
            return find;
        }

        /// <summary>
        /// 获取InputQueryXXX的类型
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        public Type FindQueryType(string entityName)
        {
            return AutoFindType("InputQuery" + ConvertToPascalCase(entityName));
        }

        /// <summary>
        /// 基于Id查询第一个数据 如果要查询Include的使用FindEntityByIdWithIncludeAsync
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="id"></param>
        /// <param name="_dbContext"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        public async Task<object> FindEntityByIdAsync(DbContext _dbContext, Type entityType, object id, CancellationToken cancellationToken = default)
        {

            var dbSet = FindDbSetObject(_dbContext, entityType);
            // 获取 FindAsync 方法
            var findAsyncMethod = dbSet.GetType()
                .GetMethod("FindAsync", new[] { typeof(object[]), typeof(CancellationToken) });
            //await _dbContext.UserInfo.FindAsync(new object[] { id,id });
            var idProperty = ReadCurrentPropertyThrowException(entityType, "Id");
            var idType = idProperty.PropertyType;
            object idobj = Convert.ChangeType(id.ToString(), idType);
            //如何把object的id转化成对应的字段类型???
            //这里是否要处理Include的情况
            // 调用方法
            var valueTask = findAsyncMethod.Invoke(dbSet, new object[] { new object[] { idobj }, 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);
            }
        }

        #region 包含Include的查询

        /// <summary>
        /// 基于Id查询第一个数据,包含Include,使用PasteIncludeAttribute标记 待测试
        /// </summary>
        /// <param name="_dbContext"></param>
        /// <param name="entityType"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<object> FindEntityByIdWithIncludeAsync(DbContext _dbContext, Type entityType, object id, CancellationToken cancellationToken = default)
        {
            // 获取 DbSet
            var dbSet = FindDbSetObject(_dbContext, entityType);

            // 构建基础查询
            var query = BuildQueryable(dbSet, entityType);

            // 自动包含所有标记了 PasteInclude 的导航属性
            query = ApplyAllPasteIncludes(query, entityType);

            // 构建过滤表达式并执行查询
            var whereExpression = BuildIdFilterExpression(entityType, id);
            var result = await ExecuteFirstAsync(query, entityType, whereExpression, cancellationToken);
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbSet"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        private object BuildQueryable(object dbSet, Type entityType)
        {
            var asQueryableMethod = typeof(Queryable)
                .GetMethods()
                .First(m => m.Name == "AsQueryable" && m.IsGenericMethod)
                .MakeGenericMethod(entityType);

            return asQueryableMethod.Invoke(null, new[] { dbSet });
        }

        /// <summary>
        /// 判断实体类型是否有任何标记了 PasteIncludeAttribute 的属性
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>true 表示有 PasteInclude 属性,需要使用 Include 版本</returns>
        public bool HasPasteIncludeProperties(Type entityType)
        {
            //return entityType.GetProperties().Any(p => p.IsDefined(typeof(PasteIncludeAttribute), false));
            return HasAttributeType(entityType, typeof(PasteIncludeAttribute));
        }

        /// <summary>
        /// 判断实体类型是否有任何标记了 XXXAttribute 的属性
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="attributeType">typeof(PasteIncludeAttribute)</param>
        /// <returns></returns>
        public bool HasAttributeType(Type entityType, Type attributeType)
        {
            return entityType.GetProperties().Any(p => p.IsDefined(attributeType, false));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        public object ApplyAllPasteIncludes(object query, Type entityType)
        {
            // 获取所有标记了 PasteInclude 特性的属性
            var pasteIncludeProperties = entityType.GetProperties()
                .Where(p => p.IsDefined(typeof(PasteIncludeAttribute), false))
                .ToList();
            foreach (var property in pasteIncludeProperties)
            {
                query = ApplyInclude(query, entityType, property.Name);
            }
            return query;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private object ApplyInclude(object query, Type entityType, string propertyName)
        {
            // 使用字符串版本的 Include 方法
            var includeMethod = typeof(EntityFrameworkQueryableExtensions)
                .GetMethods()
                .First(m => m.Name == "Include" &&
                           m.GetParameters().Length == 2 &&
                           m.GetParameters()[1].ParameterType == typeof(string))
                .MakeGenericMethod(entityType);

            return includeMethod.Invoke(null, new[] { query, propertyName });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        private LambdaExpression BuildIdFilterExpression(Type entityType, object id)
        {
            var parameter = Expression.Parameter(entityType, "x");
            var idProperty = ReadCurrentPropertyThrowException(entityType, "Id");

            var idTyped = Convert.ChangeType(id, idProperty.PropertyType);
            var left = Expression.Property(parameter, idProperty);
            var right = Expression.Constant(idTyped, idProperty.PropertyType);
            var body = Expression.Equal(left, right);

            return Expression.Lambda(body, parameter);
        }

        private async Task<object> ExecuteFirstAsync(object query, Type entityType, LambdaExpression predicate, CancellationToken cancellationToken)
        {
            // 找到正确的 FirstAsync 重载(带 predicate 的版本有3个参数)
            var firstAsyncMethod = typeof(EntityFrameworkQueryableExtensions)
                .GetMethods()
                .First(m => m.Name == "FirstAsync" &&
                           m.GetParameters().Length == 3 &&  // 应该是3个参数:query, predicate, cancellationToken
                           m.GetParameters()[0].ParameterType.IsGenericType &&
                           m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IQueryable<>))
                .MakeGenericMethod(entityType);

            // 调用方法
            var task = firstAsyncMethod.Invoke(null, new[] { query, predicate, cancellationToken });

            // 等待任务完成并获取结果
            await (Task)task;

            // 通过反射获取 Result 属性
            var resultProperty = task.GetType().GetProperty("Result");
            return resultProperty.GetValue(task);
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_dbContext"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private PropertyInfo FindDbSetProperty(DbContext _dbContext, Type entityType)
        {
            ////_dbContext.GetType().GetProperties()
            var dbSetProperty = MemoryProperties(_dbContext.GetType())
                .FirstOrDefault(p =>
                    p.PropertyType.IsGenericType &&
                    p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
                    p.PropertyType.GetGenericArguments()[0] == entityType);

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

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_dbContext"></param>
        /// <param name="entityName"></param>
        /// <returns></returns>
        public object FindDbSetObject(DbContext _dbContext, Type entityName)
        {
            var dbSetProperty = FindDbSetProperty(_dbContext, entityName);
            return dbSetProperty.GetValue(_dbContext);
        }

        /// <summary>
        /// 基于PasteMutex排重 id!=id and name==name
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="dtoType"></param>
        /// <param name="dtoValue"></param>
        /// <param name="_dbContext"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        public async Task<object> FilterFirstOrDefaultAsync(DbContext _dbContext, Type entityType, Type dtoType, object dtoValue, object id, CancellationToken cancellationToken = default)
        {
            var dbSet = FindDbSetObject(_dbContext, entityType);
            // 创建参数表达式 x
            var parameter = Expression.Parameter(entityType, "x");

            // 获取所有标记了 PasteMutexAttribute 的属性
            var properties = MemoryProperties(entityType)
                .Where(p => p.GetCustomAttributes(typeof(PasteMutexAttribute), true).Length > 0)
                .ToList();

            if (properties?.Any() == false)
            {
                return null;
            }

            //多个Mutex是否是And关系,默认为Or关系
            var boolBatch = false;
            //boolBatch = MemoryProperties(entityType).Where(p => p.GetCustomAttributes(typeof(PasteBatchMutexAttribute), true).Length > 0).Any();
            //2026-01-22 修正,应该是class的特性,而不是字段的
            boolBatch = entityType.GetCustomAttributes(typeof(PasteBatchMutexAttribute), true).Any();

            BinaryExpression condition = null;
            if (id != null)
            {
                // 创建初始条件表达式 x.Id == id
                var idProperty = ReadCurrentPropertyThrowException(entityType, "Id");
                var idPropertyAccess = Expression.Property(parameter, idProperty);
                var idValue = Convert.ChangeType(id, idProperty.PropertyType);
                var idConstant = Expression.Constant(idValue, idProperty.PropertyType);
                condition = Expression.NotEqual(idPropertyAccess, idConstant);
            }
            //非Id之外的表达式
            BinaryExpression binaryExpression = null;
            // 为每个标记了特性的属性添加条件
            foreach (var property in properties)
            {
                // 获取属性的默认值 (对于引用类型为 null,值类型为默认值)
                //object propertyValue = property.PropertyType.IsValueType
                //    ? Activator.CreateInstance(property.PropertyType)
                //    : null;

                var dtoProperty = ReadCurrentProperty(dtoType, property.Name);

                if (dtoProperty == null || dtoProperty == default)
                {
                    continue;
                }

                object propertyValue = dtoProperty.GetValue(dtoValue);

                // 创建属性访问表达式
                var propertyAccess = Expression.Property(parameter, property);

                // 创建常量表达式
                var constant = Expression.Constant(propertyValue, property.PropertyType);

                // 创建相等表达式
                var equalExpression = Expression.Equal(propertyAccess, constant);
                if (binaryExpression != null)
                {
                    if (boolBatch)
                    {
                        binaryExpression = Expression.AndAlso(binaryExpression, equalExpression);
                    }
                    else
                    {
                        binaryExpression = Expression.OrElse(binaryExpression, equalExpression);
                    }
                }
                else
                {
                    binaryExpression = equalExpression;
                }
            }

            //最终表达式
            BinaryExpression finalExpression = null;
            if (condition == null)
            {
                finalExpression = binaryExpression;
            }
            else
            {
                finalExpression = Expression.AndAlso(condition, binaryExpression);
            }

            // 创建 lambda 表达式
            var lambda = Expression.Lambda(finalExpression, parameter);

            // 获取 Where 方法
            var whereMethod = typeof(Queryable)
                .GetMethods()
                .First(m => m.Name == "Where" && m.GetParameters().Length == 2)
                .MakeGenericMethod(entityType);

            // 调用 Where 方法
            var whereQuery = whereMethod.Invoke(null, new object[] { dbSet, lambda });
            // 获取 FirstOrDefaultAsync 方法
            var firstOrDefaultAsyncMethod = typeof(EntityFrameworkQueryableExtensions)
                .GetMethods()
                .First(m => m.Name == "FirstOrDefaultAsync" && m.GetParameters().Length == 2)
                .MakeGenericMethod(entityType);

            // 调用 FirstOrDefaultAsync 方法
            var task = firstOrDefaultAsyncMethod.Invoke(null, new object[] { whereQuery, cancellationToken }) as Task;
            await task;

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

        /// <summary>
        /// 查找符合条件的第一个数据
        /// 一般用于新增,或者更新排重使用
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="args"></param>
        /// <param name="_dbContext"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        public async Task<object> FindFirstOrDefaultAsync(DbContext _dbContext, Type entityType, Dictionary<string, string> args, CancellationToken cancellationToken = default)
        {
            var dbSet = FindDbSetObject(_dbContext, entityType);
            // 创建参数表达式 x
            var parameter = Expression.Parameter(entityType, "x");
            // 获取所有标记了 PasteMutexAttribute 的属性

            //非Id之外的表达式
            BinaryExpression binaryExpression = null;
            // 为每个标记了特性的属性添加条件
            foreach (var arg in args)
            {
                var dtoProperty = ReadCurrentPropertyThrowException(entityType, arg.Key);
                object queryValue = Convert.ChangeType(arg.Value, dtoProperty.PropertyType);
                //object propertyValue = dtoProperty.GetValue(dtoValue);
                // 创建属性访问表达式
                var propertyAccess = Expression.Property(parameter, dtoProperty);
                // 创建常量表达式
                var constant = Expression.Constant(queryValue, dtoProperty.PropertyType);
                // 创建相等表达式
                var equalExpression = Expression.Equal(propertyAccess, constant);
                if (binaryExpression != null)
                {
                    // 组合条件 Andorsl 单个条件满足 及触发
                    binaryExpression = Expression.AndAlso(binaryExpression, equalExpression);
                }
                else
                {
                    binaryExpression = equalExpression;
                }
            }

            // 创建 lambda 表达式
            var lambda = Expression.Lambda(binaryExpression, parameter);

            // 获取 Where 方法
            var whereMethod = typeof(Queryable)
                .GetMethods()
                .First(m => m.Name == "Where" && m.GetParameters().Length == 2)
                .MakeGenericMethod(entityType);

            // 调用 Where 方法
            var whereQuery = whereMethod.Invoke(null, new object[] { dbSet, lambda });
            // 获取 FirstOrDefaultAsync 方法
            var firstOrDefaultAsyncMethod = typeof(EntityFrameworkQueryableExtensions)
                .GetMethods()
                .First(m => m.Name == "FirstOrDefaultAsync" && m.GetParameters().Length == 2)
                .MakeGenericMethod(entityType);

            // 调用 FirstOrDefaultAsync 方法
            var task = firstOrDefaultAsyncMethod.Invoke(null, new object[] { whereQuery, cancellationToken }) as Task;
            await task;

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

        /// <summary>
        /// 动态读取模型属性
        /// </summary>
        /// <param name="model"></param>
        /// <param name="modelType"></param>
        /// <param name="IsListModel">针对枚举的备注过滤</param>
        /// <returns></returns>
        public VoloModelInfo ReadModelProperties(object model, Type modelType, bool IsListModel = false)
        {
            return BuilderHelper.AttributeReadModelProperty(model, modelType, IsListModel);
        }

        /// <summary>
        /// 单词大小写转化
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private static 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);
        }

        /// <summary>
        /// 验证输入是否通过校验
        /// </summary>
        /// <param name="model"></param>
        /// <param name="modelType"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="PasteCodeException"></exception>
        public 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("输入数据验证失败" + errorMessages[0], 400);
            }
        }

        /// <summary>
        /// 补充Extend外表查询 比如ExtendUser 可能有多个
        /// </summary>
        /// <param name="listDtoType"></param>
        /// <param name="dtos"></param>
        /// <param name="_dbContext"></param>
        /// <returns></returns>
        public async Task BuildOuterData(DbContext _dbContext, Type listDtoType, List<object> dtos)
        {
            var sears = MemoryProperties(listDtoType).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;//RoleInfo
                        var to_extend = short_attr.Args2;//ExtendUser

                        if (String.IsNullOrEmpty(out_entity_name))
                        {
                            //Logger.LogInformation($"FullName:{listDtoType.FullName} Has Short Attribute!");
                            continue;
                        }
                        else
                        {
                            //Serilog.Log.Information($"{nameof(DefaultHelper)} FullName:{listDtoType.FullName} Has Short Attribute Args1:{short_attr.Args1} Args2:{short_attr.Args2}!");
                            //Logger.LogInformation($"FullName:{listDtoType.FullName} Has Short Attribute Args1:{short_attr.Args1} Args2:{short_attr.Args2}!");
                        }

                        var target_property = MemoryProperties(listDtoType).Where(x => string.Equals(x.Name, to_extend, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                        if (target_property == null || target_property == default)
                        {
                            continue;
                        }

                        var relatedDtoType = target_property.PropertyType;

                        var ids = new List<object>();
                        foreach (var dto in dtos)
                        {
                            //var id = dto.GetType().GetProperty(out_id_field, BindingFlags.Public | BindingFlags.Instance)?.GetValue(dto);
                            var id = ReadCurrentProperty(dto.GetType(), out_id_field)?.GetValue(dto);//.GetProperty(out_id_field, BindingFlags.Public | BindingFlags.Instance)?.GetValue(dto);
                            if (id != null && !ids.Contains(id))
                            {
                                ids.Add(id);
                            }
                        }
                        if (ids.Count > 0)
                        {
                            //从数据库读取数据
                            var relatedEntityType = FindEntityType(out_entity_name);
                            //转换成对应的dto
                            //赋值
                            if (relatedEntityType == null)
                            {
                                continue;
                            }
                            // 构建ID查询条件
                            var relatedQuery = BuildIdQuery(_dbContext, relatedEntityType, ids);
                            if (relatedQuery != null)
                            {
                                //直接查询Dto
                                var relatedDtos = await ExecuteProjectionQuery(relatedQuery, relatedEntityType, relatedDtoType);

                                // 3. 创建ID到DTO的映射字典
                                //var idToDto = relatedDtos.ToDictionary(d => d.GetType().GetProperty("Id", BindingFlags.Public | BindingFlags.Instance)?.GetValue(d));
                                var idToDto = relatedDtos.ToDictionary(d => ReadCurrentProperty(d.GetType(), "Id")?.GetValue(d));
                                // 4. 填充到主表DTO
                                foreach (var dto in dtos)
                                {
                                    //获取UserId的值
                                    //var id = dto.GetType().GetProperty(out_id_field, BindingFlags.Public | BindingFlags.Instance)?.GetValue(dto);
                                    var id = ReadCurrentProperty(dto.GetType(), out_id_field)?.GetValue(dto);//.GetProperty(out_id_field, BindingFlags.Public | BindingFlags.Instance)?.GetValue(dto);
                                    if (id != null && idToDto.TryGetValue(id, out var relatedDto))
                                    {
                                        //给ExtendUser填充值
                                        ReadCurrentProperty(dto.GetType(), to_extend)?.SetValue(dto, relatedDto);//.GetProperty(to_extend, BindingFlags.Public | BindingFlags.Instance)?.SetValue(dto, relatedDto);
                                    }
                                }
                            }

                        }

                    }
                }
            }
        }

        /// <summary>
        /// 校验外表是否合法 PasteLink的校验
        /// </summary>
        /// <param name="_dbContext"></param>
        /// <param name="entityType"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task CheckEntityShortData(DbContext _dbContext, Type entityType, object entity)
        {
            // TODO:下面有问题,outer的args1有可能是一个路径... .. .
            //PasteLink PateInclude 标记OuterId和Include模式
            var sears = MemoryProperties(entityType).Where(x => x.GetCustomAttributes<PasteLinkAttribute>().Any()).ToList();
            if (sears?.Any() == true)
            {
                foreach (var _search in sears)
                {
                    var outerValue = _search.GetValue(entity);
                    if (outerValue == null)
                    {
                        continue;
                    }
                    if (outerValue.ToString() == "0")
                    {
                        continue;
                    }
                    //if(_search.GetValue)
                    var short_attr = _search.GetCustomAttributes<PasteLinkAttribute>().FirstOrDefault();
                    if (short_attr != null && short_attr != default)
                    {
                        var outerEntityName = short_attr.Args1;//RoleInfo
                        if (String.IsNullOrEmpty(outerEntityName))
                        {
                            Serilog.Log.Warning($"{entityType.Name}.{_search.Name}.PasteLink.Args1 配置不能为空!");
                            continue;
                        }
                        var outerEntityType = FindEntityType(outerEntityName);
                        if (outerEntityType == null)
                        {

                            Serilog.Log.Warning($"没有找到:{short_attr.Args1}的 Entity!");
                            continue;
                        }
                        var args = new Dictionary<string, string> { };
                        args.Add("Id", outerValue.ToString());
                        var first = await this.FindFirstOrDefaultAsync(_dbContext, outerEntityType, args);
                        if (first == null)
                        {
                            throw new PasteCodeException($"没有从:{outerEntityName} 中找到对象:{outerValue.ToString()} !");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 构建搜索项
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="searchType"></param>
        /// <param name="input"></param>
        /// <param name="_dbContext"></param>
        /// <returns></returns>
        public IQueryable BuildDynamicQuery(DbContext _dbContext, Type entityType, Type searchType, object input)
        {
            var dbSet = FindDbSetObject(_dbContext, entityType);
            // 获取IQueryable接口
            var queryable = (IQueryable)dbSet;
            // 获取所有属性(包括继承的)
            var selectedProperties = ReadTypeProperties(searchType);
            //var entityProperties = ReadTypeProperties(entityType);
            queryable = ApplyFilterConditions(queryable, entityType, selectedProperties, input);
            // 应用过滤条件
            return queryable;
        }

        /// <summary>
        /// 获取目标类型的PropertyInfo,如果有new的则进行基类过滤
        /// </summary>
        /// <param name="searchType"></param>
        /// <returns></returns>
        private PropertyInfo[] ReadTypeProperties(Type searchType)
        {

            var typeName = searchType.FullName;
            // 使用GetOrCreate替代TryGetValue+Set
            return _memoryCache.GetOrCreate(typeName, entry =>
            {
                // 这里的逻辑只会被一个线程执行(其他线程等待)
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(1800); // 设置过期时间
                                                                                    //return t.GetProperties(); // 耗时的反射操作
                var allProperties = searchType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

                // 如果有属性被隐藏(new),才需要复杂处理
                var hasDuplicates = allProperties.Length != allProperties.Select(p => p.Name).Distinct().Count();
                if (!hasDuplicates)
                {
                    // 没有重复属性名,直接返回
                    return allProperties;
                }
                // 有重复属性名,进行分组处理
                var propertyGroups = allProperties.GroupBy(p => p.Name);
                var result = new PropertyInfo[propertyGroups.Count()];

                int index = 0;
                foreach (var group in propertyGroups)
                {
                    // 手动查找,避免 LINQ 的开销
                    PropertyInfo selected = null;
                    foreach (var prop in group)
                    {
                        if (prop.DeclaringType == searchType)
                        {
                            selected = prop;
                            break;  // 找到当前类声明的,立即退出
                        }
                        selected ??= prop;  // 否则保留第一个
                    }
                    result[index++] = selected!;
                }

                return result;
            });

        }

        /// <summary>
        /// 应用过滤条件的方法
        /// 后续要优化成 entityProperties和searchProperties
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="searchProperties"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        private IQueryable ApplyFilterConditions(IQueryable query, Type entityType, PropertyInfo[] searchProperties, object input)
        {
            //需要忽略的字段,一般表示处理过了,或者是内置有特殊用法的字段
            var ignors = new List<string> { "page", "size", "orderby" };
            foreach (var inputProperty in searchProperties)
            {
                if (ignors.Contains(inputProperty.Name))
                {
                    continue;
                }
                // 获取属性值 空值 0 等的处理
                var value = inputProperty.GetValue(input);
                if (IsDefaultValue(value, inputProperty.PropertyType))
                {
                    //Serilog.Log.Information($"由于默认值为空,被忽略了:{inputProperty.Name} ");
                    continue;
                }
                // 特殊处理搜索关键词
                if (inputProperty.Name == "word" && !string.IsNullOrEmpty(value?.ToString()))
                {
                    //是否要一个字段标记这个?
                    query = ApplySearchKeyword(query, entityType, value.ToString());
                    continue;
                }
                //实际查询字段 比如level_str映射到实际中的Level,其实就是读取PasteField
                var entityProperty = FindSearchProperty(inputProperty, entityType);
                if (entityProperty != null)
                {
                    #region 基于时间区间查询,比如查询2025-05-01 00:00:00 - 2025-06-01 00:00:00 注册的用户,包含开始时间
                    var btype = inputProperty.PropertyType;
                    //时间区间查询处理
                    if (btype == typeof(DateTime) || btype == typeof(DateTime?))
                    {
                        var find = inputProperty.GetCustomAttributes<PasteDaterangeAttribute>().FirstOrDefault();
                        if (find != null && find != default)
                        {
                            var edate_pro = find.Args2;
                            var sdate_str = inputProperty.GetValue(input);
                            var end_property = searchProperties.Where(x => String.Equals(x.Name, edate_pro, StringComparison.OrdinalIgnoreCase)).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))
                                    {
                                        query = ApplyComparisonFilter(query, entityType, entityProperty, sdate, "GreaterThanOrEqual");
                                        query = ApplyComparisonFilter(query, entityType, entityProperty, edate, "LessThan");
                                    }
                                }
                            }
                            ignors.Add(edate_pro);
                            continue;
                        }
                    }
                    #endregion

                    #region 基于数据段查询,比如查询成绩80-90分的学生,包含80不包含90
                    var isRange = inputProperty.GetCustomAttributes<PasteSearchRangeAttribute>().FirstOrDefault();
                    if (isRange != null && isRange != default)
                    {
                        var edate_pro = isRange.Args2;
                        var sdate_str = inputProperty.GetValue(input);
                        var end_property = searchProperties.Where(x => String.Equals(x.Name, edate_pro, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                        if (end_property != null && end_property != default)
                        {
                            var edate_str = end_property.GetValue(input).ToString();
                            var sdate = Convert.ChangeType(sdate_str, entityProperty.PropertyType);
                            var edate = Convert.ChangeType(edate_str, entityProperty.PropertyType);
                            query = ApplyComparisonFilter(query, entityType, entityProperty, sdate, "GreaterThanOrEqual");
                            query = ApplyComparisonFilter(query, entityType, entityProperty, edate, "LessThan");
                        }
                        ignors.Add(edate_pro);
                        continue;
                    }
                    #endregion

                    // 处理枚举类型
                    if (inputProperty.PropertyType.IsEnum)
                    {
                        var enumValue = Enum.ToObject(inputProperty.PropertyType, value);
                        if (entityProperty.PropertyType == inputProperty.PropertyType.GetElementType())
                        {
                            // 枚举值为0表示全部,不进行查询
                            if (value is int intValue && intValue == 0)
                            {
                                continue;
                            }
                            // 将值转换为正确的枚举类型
                            //var enumValue = Enum.ToObject(property.PropertyType, value);
                            query = ApplyComparisonFilter(query, entityType, entityProperty, enumValue, ReturnOperator(inputProperty));
                            continue;
                        }
                        else
                        {
                            if (entityProperty.PropertyType == typeof(bool))
                            {
                                // 更健壮的布尔值判断
                                string enumString = enumValue.ToString().Trim();
                                bool boolValue;

                                if (bool.TryParse(enumString, out boolValue))
                                {
                                    // 如果能直接解析为bool
                                    query = ApplyComparisonFilter(query, entityType, entityProperty, boolValue, ReturnOperator(inputProperty));
                                }
                                else if (enumString.Equals("1"))
                                {
                                    // 处理数字1表示true的情况
                                    query = ApplyComparisonFilter(query, entityType, entityProperty, true, ReturnOperator(inputProperty));
                                }
                                else if (enumString.Equals("0"))
                                {
                                    // 处理数字0表示false的情况
                                    //query = ApplyComparisonFilter(query, entityType, entityProperty, false, ReturnOperator(inputProperty));
                                    continue;
                                }
                                else
                                {
                                    // 默认处理:任何无法识别的值都视为false,或者根据需求抛出异常
                                    query = ApplyComparisonFilter(query, entityType, entityProperty, false, ReturnOperator(inputProperty));
                                    // 或者抛出异常:throw new ArgumentException($"无法将值 '{enumString}' 转换为布尔类型");
                                }
                                continue;
                            }
                        }
                        //转化成需要的类型,比如输入是枚举,数据库中是Int
                        var change_value = Convert.ChangeType(enumValue, entityProperty.PropertyType);
                        query = ApplyComparisonFilter(query, entityType, entityProperty, change_value, ReturnOperator(inputProperty));
                        continue;
                    }

                    // 处理枚举数组类型
                    if (inputProperty.PropertyType.IsArray)
                    {
                        if (inputProperty.PropertyType.GetElementType().IsEnum)
                        {
                            if (entityProperty.PropertyType == inputProperty.PropertyType.GetElementType())
                            {
                                // 如果传入的是数组,直接使用
                                if (value is Array enumArray)
                                {
                                    query = ApplyComparisonFilter(query, entityType, entityProperty, value, ReturnOperator(inputProperty));
                                }
                                else
                                {
                                    // 如果传入的是单个值,转换为单元素数组 这里应该是有问题的,因为上一级已经处理这个转化了... .. .
                                    var elementType = inputProperty.PropertyType.GetElementType();
                                    var array = Array.CreateInstance(elementType, 1);
                                    array.SetValue(Enum.ToObject(elementType, value), 0);
                                    query = ApplyComparisonFilter(query, entityType, entityProperty, array, ReturnOperator(inputProperty));
                                }
                            }
                            else
                            {
                                // 输入是enum[]类型,表类型是int
                                // 使用枚举类型的泛型列表替代object列表
                                var enumType = Nullable.GetUnderlyingType(entityProperty.PropertyType) ?? entityProperty.PropertyType;
                                var arrs = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(enumType));

                                // 如果传入的是数组,直接使用
                                if (value is Array enumArray)
                                {
                                    foreach (var item in enumArray)
                                    {
                                        if (item != null)
                                        {
                                            var nval = Convert.ChangeType(item, enumType);
                                            arrs.Add(nval);
                                        }
                                    }
                                }
                                // 如果传入的是单个值,转换为单元素数组
                                else if (value != null)
                                {
                                    var nval = Convert.ChangeType(value, enumType);
                                    arrs.Add(nval);
                                }

                                if (arrs?.Count == 0)
                                {
                                    continue;
                                }
                                query = ApplyComparisonFilter(query, entityType, entityProperty, arrs, ReturnOperator(inputProperty));
                            }
                            continue;
                        }
                        else
                        {
                            //其他类型 比如Int32[] UInt32[]等
                            //什么情况下 检索是array而不是枚举,比如传入ags_array 基于年龄查询... .. .
                            query = ApplyComparisonFilter(query, entityType, entityProperty, value, ReturnOperator(inputProperty));
                            continue;
                        }
                    }

                    //转化到数据库字段类型,然后进行过滤
                    var new_val = Convert.ChangeType(value.ToString(), entityProperty.PropertyType);
                    if (new_val != null)
                    {
                        query = ApplyComparisonFilter(query, entityType, entityProperty, new_val, ReturnOperator(inputProperty));
                    }
                    else
                    {
                        //Serilog.Log.Information($"转化失败,无法继续查询 :{inputProperty.Name} ");
                    }
                }
                else
                {
                    //Serilog.Log.Information($"{nameof(DefaultHelper)} {inputProperty.Name} 没有找到检索字段对应Entity的Property信息,是否是未标记PasteField特性!");
                }
            }

            // 自动包含所有标记了 PasteInclude 的导航属性
            //query = ApplyAllPasteIncludes(query, entityType);

            return query;
        }

        /// <summary>
        /// 获取运算符
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        private static 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))
                    {
                        switch (find.Args2)
                        {
                            case "=": return "Equals";
                            case "!=": return "NotEquals";
                            case ">": return "GreaterThan";
                            case ">=": return "GreaterThanOrEqual";
                            case "<": return "LessThan";
                            case "<=": return "LessThanOrEqual";
                            case "()": return "Contains";
                            default: return "Equals";
                        }
                    }
                }
            }
            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 = ReadCurrentProperty(entityType, target_property);
            if (entityProperty != null)
            {
                return entityProperty;
            }
            return null;
        }

        /// <summary>
        /// 判断值是否为类型的默认值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static 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());
            }
            var strValue = value.ToString();
            if (String.IsNullOrEmpty(strValue) || strValue == "0")
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 应对有 new 字段的情况
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="entityType"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private static MemberExpression GetPropertyAccess(ParameterExpression parameter, Type entityType, string propertyName)
        {
            try
            {
                // 方法1:尝试获取当前类声明的属性(包括new的)
                var property = entityType.GetProperty(propertyName,
                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

                if (property != null)
                    return Expression.Property(parameter, property);

                // 方法2:如果没有,获取继承的属性
                property = entityType.GetProperty(propertyName);
                return Expression.Property(parameter, property);
            }
            catch (AmbiguousMatchException)
            {
                // 方法3:如果出现歧义,手动选择
                var properties = entityType.GetProperties(
                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

                var property = properties.FirstOrDefault(p => p.Name == propertyName)
                    ?? entityType.GetProperty(propertyName); // 回退

                return Expression.Property(parameter, property);
            }
        }

        /// <summary>
        /// 后续需要优化下 不然每次都获取Properties 主要是针对继承等情况... .. .
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <param name="operatorName"></param>
        /// <returns></returns>
        private static IQueryable ApplyComparisonFilter(IQueryable query, Type entityType, PropertyInfo property, object value, string operatorName = "Equals")
        {

            //Se.LogInformation($"Apply Query Queryable Property:{property.Name} Value:{value.ToString()} Operator:{operatorName}");

            var parameter = Expression.Parameter(entityType, "x");
            //var propertyAccess = Expression.Property(parameter, property.Name);
            var propertyAccess = GetPropertyAccess(parameter, entityType, property.Name);
            Expression comparisonExpression;

            switch (operatorName)
            {
                case "Equals":
                    // 处理数组/集合的等于查询(实际上是IN查询)
                    if (value is IEnumerable && !(value is string))
                    {
                        var containsMethod = typeof(Enumerable).GetMethods()
                            .First(m => m.Name == "Contains" && m.GetParameters().Length == 2)
                            .MakeGenericMethod(property.PropertyType);

                        comparisonExpression = Expression.Call(
                            null,
                            containsMethod,
                            Expression.Constant(value),
                            propertyAccess);
                    }
                    else
                    {
                        var constant = Expression.Constant(value, property.PropertyType);
                        comparisonExpression = Expression.Equal(propertyAccess, constant);
                    }
                    break;

                case "NotEquals":
                    var notEqualConstant = Expression.Constant(value, property.PropertyType);
                    comparisonExpression = Expression.NotEqual(propertyAccess, notEqualConstant);
                    break;

                case "GreaterThan":
                    var gtConstant = Expression.Constant(value, property.PropertyType);
                    comparisonExpression = Expression.GreaterThan(propertyAccess, gtConstant);
                    break;

                case "GreaterThanOrEqual":
                    var gteConstant = Expression.Constant(value, property.PropertyType);
                    comparisonExpression = Expression.GreaterThanOrEqual(propertyAccess, gteConstant);
                    break;

                case "LessThan":
                    var ltConstant = Expression.Constant(value, property.PropertyType);
                    comparisonExpression = Expression.LessThan(propertyAccess, ltConstant);
                    break;

                case "LessThanOrEqual":
                    var lteConstant = Expression.Constant(value, property.PropertyType);
                    comparisonExpression = Expression.LessThanOrEqual(propertyAccess, lteConstant);
                    break;

                case "Contains":
                    // 处理字符串Contains
                    if (property.PropertyType == typeof(string))
                    {
                        var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                        comparisonExpression = Expression.Call(propertyAccess, containsMethod, Expression.Constant(value));
                    }
                    // 处理集合Contains(查询值是否在集合中)
                    else if (value is IEnumerable && !(value is string))
                    {
                        var containsMethod = typeof(Enumerable).GetMethods()
                            .First(m => m.Name == "Contains" && m.GetParameters().Length == 2)
                            .MakeGenericMethod(property.PropertyType);

                        comparisonExpression = Expression.Call(
                            null,
                            containsMethod,
                            Expression.Constant(value),
                            propertyAccess);
                    }
                    // 处理其他类型的Contains(如List<T>.Contains)
                    else
                    {
                        var containsMethod = property.PropertyType.GetMethod("Contains", new[] { property.PropertyType.GenericTypeArguments[0] });
                        comparisonExpression = Expression.Call(propertyAccess, containsMethod, Expression.Constant(value));
                    }
                    break;

                default:
                    comparisonExpression = Expression.Equal(propertyAccess, Expression.Constant(value, property.PropertyType));
                    break;
            }

            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)
        {
            // 外部已确保keyword非空,这里仅做防御性校验
            if (string.IsNullOrEmpty(keyword))
            {
                return query;
            }

            var stringProperties = MemoryProperties(entityType)
                .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>
        /// 上面的补充,用于其他查询
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <param name="searchType"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        public IQueryable ApplyPagingAndSorting(IQueryable query, Type entityType, Type searchType, Object input)
        {
            // 获取Id属性信息
            var idProperty = ReadCurrentPropertyThrowException(entityType, "Id");//.GetProperties().Where(x => x.Name == "Id").LastOrDefault();
            var page = 1;
            var size = 20;
            var orderby = String.Empty;
            foreach (var ii in MemoryProperties(searchType))
            {
                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;
                }
            }
            var actionOrderby = false;
            if (!String.IsNullOrEmpty(orderby))
            {
                #region 下面是旧版本,只支持单个排序
                //var fieldName = orderby.Split(" ")[0];
                //var findOrderProperty = ReadCurrentProperty(entityType, fieldName);
                //if (findOrderProperty != null)
                //{
                //    var orderType = "OrderByDescending";
                //    if (!orderby.Contains(" desc", StringComparison.OrdinalIgnoreCase))
                //    {
                //        orderType = "OrderBy";
                //    }
                //    // 构建排序表达式 默认 OrderByDescending(x=>x.Id)
                //    var parameter = Expression.Parameter(entityType, "x");
                //    var propertyAccess = Expression.Property(parameter, findOrderProperty);
                //    var lambda = Expression.Lambda(propertyAccess, parameter);
                //    // 使用正确的属性类型作为排序键类型
                //    var orderByDescendingCall = Expression.Call(
                //        typeof(Queryable), orderType,
                //        new Type[] { entityType, findOrderProperty.PropertyType }, // 使用实际的属性类型
                //        query.Expression,
                //        lambda);
                //    query = query.Provider.CreateQuery(orderByDescendingCall);
                //    actionOrderby = true;
                //}
                #endregion

                //Console.WriteLine(orderby);
                //支持多个查询,比如id,name desc
                query = PasteOrder(query, orderby);
                actionOrderby = true;
            }
            if (!actionOrderby)
            {
                // 构建排序表达式 默认 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>
        /// 支持多排序 比如id,name desc等
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ordering"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        private IOrderedQueryable PasteOrder(IQueryable query, string ordering)
        {
            //if (string.IsNullOrWhiteSpace(ordering))
            //return query.OrderBy(x => 1);
            if (String.IsNullOrEmpty(ordering))
            {
                return (IOrderedQueryable)query;
            }
            // 分割多个排序字段
            var orderClauses = ordering.Split(',', StringSplitOptions.RemoveEmptyEntries);
            IOrderedQueryable orderedQuery = null;
            var eType = query.ElementType;
            foreach (var clause in orderClauses)
            {
                var parts = clause.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 0) continue;

                var fieldName = parts[0];
                var descending = false;
                if (parts.Length > 1)
                {
                    descending = parts.Length > 1 &&
                                   (parts[1].Equals("desc", StringComparison.OrdinalIgnoreCase) ||
                                    parts[1].Equals("descending", StringComparison.OrdinalIgnoreCase));
                }
                var propertyInfo = ReadTypeProperties(eType).FirstOrDefault(x => string.Equals(x.Name, fieldName, StringComparison.OrdinalIgnoreCase));
                if (propertyInfo == null)
                {
                    throw new ArgumentException($"类型 '{eType.Name}' 中不存在属性 '{fieldName}'");
                }

                // 构建表达式
                var parameter = Expression.Parameter(eType, "x");
                var property = Expression.Property(parameter, propertyInfo);
                var lambda = Expression.Lambda(property, parameter);

                if (orderedQuery == null)
                {
                    // 第一个排序字段
                    var methodName = descending ? "OrderByDescending" : "OrderBy";
                    var methodCall = Expression.Call(
                        typeof(Queryable), methodName,
                        new Type[] { eType, property.Type },
                        query.Expression, Expression.Quote(lambda));

                    orderedQuery = (IOrderedQueryable)query.Provider.CreateQuery(methodCall);
                }
                else
                {
                    // 后续排序字段
                    var methodName = descending ? "ThenByDescending" : "ThenBy";
                    var methodCall = Expression.Call(
                        typeof(Queryable), methodName,
                        new Type[] { eType, property.Type },
                        orderedQuery.Expression, Expression.Quote(lambda));

                    orderedQuery = (IOrderedQueryable)orderedQuery.Provider.CreateQuery(methodCall);
                }
            }
            return orderedQuery ?? (IOrderedQueryable)query;
        }

        /// <summary>
        /// 查找字段 应对new的情况
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        /// <exception cref="PasteCodeException"></exception>
        private PropertyInfo ReadCurrentPropertyThrowException(Type entityType, string propertyName)
        {
            var read = ReadCurrentProperty(entityType, propertyName);
            if (read != null)
            {
                return read;
            }
            // 3. 找不到Id属性
            throw new PasteCodeException($"实体 {entityType.Name} 不包含{propertyName}属性", 500);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public PropertyInfo ReadCurrentProperty(Type entityType, string propertyName)
        {
            var properties = ReadTypeProperties(entityType);
            if (properties != null)
            {
                //var find = properties.FirstOrDefault(x => x.Name == propertyName);
                var find = properties.FirstOrDefault(x => string.Equals(x.Name, propertyName, StringComparison.OrdinalIgnoreCase));
                if (find != null)
                {
                    return find;
                }
            }
            return null;
        }

        /// <summary>
        /// 执行计数查询的方法
        /// </summary>
        /// <param name="query"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        public 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>
        /// 直接查询并投影为DTO 这个有问题,Include等不足
        /// </summary>
        public async Task<List<object>> ExecuteProjectionQuery(IQueryable query, Type entityType, Type dtoType)
        {
            // 构建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));
            var task = (Task)toListMethod.Invoke(null, new object[] { projectedQuery, CancellationToken.None });
            await task;
            var resultProperty = task.GetType().GetProperty("Result");
            return (List<object>)resultProperty.GetValue(task);
        }

        /// <summary>
        /// 执行包含 Include 的查询并映射到 DTO 旧版本ExecuteProjectionQuery
        /// </summary>
        public async Task<List<object>> ExecuteProjectionQueryWithIncludes(IQueryable query, Type entityType, Type dtoType)
        {
            try
            {
                // 执行查询获取包含 Include 的实体列表
                var toListAsyncMethod = typeof(EntityFrameworkQueryableExtensions)
                    .GetMethods()
                    .First(m => m.Name == "ToListAsync" && m.GetParameters().Length == 2)
                    .MakeGenericMethod(entityType);

                var task = (Task)toListAsyncMethod.Invoke(null, new object[] { query, CancellationToken.None });
                await task;

                var resultProperty = task.GetType().GetProperty("Result");
                var entityList = resultProperty.GetValue(task);
                if (entityList == null) { return null; }
                //Console.WriteLine($"{Newtonsoft.Json.JsonConvert.SerializeObject(entityList)}");
                // 使用 ObjectMapper 将实体列表映射到 DTO 列表
                return MapEntityListToDtoListDirectly(entityList, entityType, dtoType);
            }
            catch (Exception ex)
            {
                Serilog.Log.Error(ex, "执行包含 Include 的投影查询失败");
                throw;
            }
        }

        /// <summary>
        /// 直接映射整个实体列表到 DTO 列表
        /// </summary>
        private List<object> MapEntityListToDtoListDirectly(object entityList, Type entityType, Type dtoType)
        {
            try
            {
                if (entityList == null) return null;
                // 修正:使用 TypeAdapter.Adapt 静态方法
                var result = Mapster.TypeAdapter.Adapt(entityList, entityList.GetType(), typeof(List<>).MakeGenericType(dtoType));
                if (result is System.Collections.IList list)
                {
                    return new List<object>(list.Cast<object>());
                }
                return null;
            }
            catch (Exception ex)
            {
                Serilog.Log.Warning(ex, "列表映射失败");
                return null;
            }

        }


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

            // 创建DTO属性的绑定
            var bindings = MemoryProperties(dtoType)
                .Where(p => p.CanWrite)
                .Select(p =>
                {
                    // 查找实体类型中是否有同名属性
                    //var entityProperty = entityType.GetProperty(p.Name, BindingFlags.Public | BindingFlags.Instance);
                    var entityProperty = ReadCurrentProperty(entityType, p.Name);// entityType.GetProperty(p.Name, BindingFlags.Public | BindingFlags.Instance);
                    if (entityProperty != null && entityProperty.CanRead)
                    {
                        if (entityProperty.PropertyType == p.PropertyType)
                        {
                            var propertyAccess = Expression.Property(parameter, entityProperty);
                            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>
        /// <param name="_dbContext"></param>
        /// <param name="entityType"></param>
        /// <param name="ids"></param>
        /// <returns></returns>
        private IQueryable BuildIdQuery(DbContext _dbContext, Type entityType, List<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 dbSet = FindDbSetObject(_dbContext, entityType);
            var queryable = (IQueryable)dbSet;

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

            var propertyAccess = Expression.Property(parameter, idProperty);

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

            ConstantExpression constant;
            if (idProperty.PropertyType == typeof(int))
            {
                List<int> id_keys = new List<int>();
                foreach (var ii in ids)
                {
                    if (int.TryParse(ii.ToString(), out var _id))
                    {
                        if (_id == 0) { continue; }
                        id_keys.Add(_id);
                    }
                }
                if (id_keys.Count == 0)
                {
                    return null;
                }
                constant = Expression.Constant(id_keys);
            }
            else if (idProperty.PropertyType == typeof(long))
            {
                List<long> id_keys = new List<long>();
                foreach (var ii in ids)
                {
                    if (long.TryParse(ii.ToString(), out var _id))
                    {
                        if (_id == 0) { continue; }
                        id_keys.Add(_id);
                    }
                }
                if (id_keys.Count == 0)
                {
                    return null;
                }
                constant = Expression.Constant(id_keys);
            }
            else if (idProperty.PropertyType == typeof(Guid))
            {
                List<Guid> id_keys = new List<Guid>();
                foreach (var ii in ids)
                {
                    if (Guid.TryParse(ii.ToString(), out var _id))
                    {
                        if (_id == Guid.Empty) { continue; }
                        id_keys.Add(_id);
                    }
                }
                if (id_keys.Count == 0)
                {
                    return null;
                }
                constant = Expression.Constant(id_keys);
            }
            else
            {
                List<string> id_keys = new List<string>();
                foreach (var ii in ids)
                {
                    var id_str = ii.ToString();
                    if (!String.IsNullOrEmpty(id_str))
                    {
                        id_keys.Add(id_str);
                    }
                }
                if (id_keys.Count == 0)
                {
                    return null;
                }
                constant = Expression.Constant(id_keys);
            }

            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);
        }

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

        /// <summary>
        /// 结果映射到实体Dto中
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        /// <param name="sourceType"></param>
        /// <param name="destinationType"></param>
        public void ForeachMapProperties(object source, object destination, Type sourceType, Type destinationType)
        {
            // 获取源类型的所有可读属性
            var sourceProperties = MemoryProperties(sourceType)
                .Where(p => p.CanRead)
                .ToList();

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

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

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

        /// <summary>
        /// 使用 ObjectMapper 进行对象映射
        /// </summary>
        public void MapProperties(object source, object destination, Type sourceType, Type destinationType)
        {
            //下面这个不支持继承
            //source.Adapt(destination, sourceType, destinationType);
            //var target = Activator.CreateInstance(destinationType);
            var sourceProps = sourceType.GetProperties();
            var targetProps = destinationType.GetProperties();
            foreach (var sp in sourceProps)
            {
                var tp = targetProps.FirstOrDefault(p => p.Name == sp.Name && p.CanWrite);
                if (tp != null)
                {
                    var val = sp.GetValue(source);
                    if (val != null && tp.PropertyType.IsAssignableFrom(val.GetType()))
                    {
                        tp.SetValue(destination, val);
                    }
                }
            }
            //return target;
        }

    }
}
​ ​