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