using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; using YY.Admin.Core.Extension; namespace YY.Admin.Core { /// /// 数据集合拓展类 /// public static class EnumerableExtension { private static readonly ConcurrentDictionary PropertyCache = new(); /// /// 查询有父子关系的数据集 /// /// 数据集 /// 主键ID字段 /// 父级字段 /// 顶级节点父级字段值 /// 是否包含顶级节点本身 /// public static IEnumerable ToChildList(this IEnumerable list, Expression> idExpression, Expression> parentIdExpression, object topParentIdValue, bool isContainOneself = true) { if (list == null || !list.Any()) return Enumerable.Empty(); var propId = GetPropertyInfo(idExpression); var propParentId = GetPropertyInfo(parentIdExpression); // 查找所有顶级节点 var topNodes = list.Where(item => Equals(propId.GetValue(item), topParentIdValue)).ToList(); return TraverseHierarchy(list, propId, propParentId, topNodes, isContainOneself); } /// /// 查询有父子关系的数据集 /// /// 数据集 /// 主键ID字段 /// 父级字段 /// 顶级节点的选择条件 /// 是否包含顶级节点本身 /// public static IEnumerable ToChildList(this IEnumerable list, Expression> idExpression, Expression> parentIdExpression, Expression> topLevelPredicate, bool isContainOneself = true) { if (list == null || !list.Any()) return Enumerable.Empty(); // 获取顶级节点 var topNodes = list.Where(topLevelPredicate.Compile()).ToList(); if (!topNodes.Any()) return Enumerable.Empty(); var idPropertyInfo = GetPropertyInfo(idExpression); var parentPropertyInfo = GetPropertyInfo(parentIdExpression); return TraverseHierarchy(list, idPropertyInfo, parentPropertyInfo, topNodes, isContainOneself); } /// /// 辅助方法,从表达式中提取属性信息并使用临时缓存 /// private static PropertyInfo GetPropertyInfo(Expression> expression) { // 使用 ConcurrentDictionary 确保线程安全 return PropertyCache.GetOrAdd(typeof(T).FullName + "." + ((MemberExpression)expression.Body).Member.Name, k => { if (expression.Body is UnaryExpression { Operand: MemberExpression member }) return (PropertyInfo)member.Member; if (expression.Body is MemberExpression memberExpression) return (PropertyInfo)memberExpression.Member; throw new Exception("表达式必须是一个属性访问: " + expression); }); } /// /// 使用队列遍历层级结构 /// private static IEnumerable TraverseHierarchy(IEnumerable list, PropertyInfo idPropertyInfo, PropertyInfo parentPropertyInfo, List topNodes, bool isContainOneself) { var queue = new Queue(topNodes); var result = new HashSet(topNodes); while (queue.Count > 0) { var currentNode = queue.Dequeue(); var children = list.Where(item => Equals(parentPropertyInfo.GetValue(item), idPropertyInfo.GetValue(currentNode))).ToList(); children.Where(child => result.Add(child)).ForEach(child => queue.Enqueue(child)); } if (isContainOneself) return result; // 如果不需要包含顶级节点本身,则移除它们 topNodes.ForEach(e => result.Remove(e)); return result; } } }