147 lines
4.0 KiB
C#
147 lines
4.0 KiB
C#
using JNPF.Common.Extension;
|
||
using JNPF.DependencyInjection;
|
||
|
||
namespace JNPF.Common.Security;
|
||
|
||
/// <summary>
|
||
/// 树结构帮助类.
|
||
/// </summary>
|
||
[SuppressSniffer]
|
||
public static class TreeHelper
|
||
{
|
||
/// <summary>
|
||
/// 建造树结构.
|
||
/// </summary>
|
||
/// <param name="allNodes">所有的节点.</param>
|
||
/// <param name="parentId">节点.</param>
|
||
/// <returns></returns>
|
||
public static List<T> ToTree<T>(this List<T> allNodes, string parentId = "0")
|
||
where T : TreeModel, new()
|
||
{
|
||
List<T> resData = new List<T>();
|
||
|
||
// 查找出父类对象
|
||
List<T> rootNodes = allNodes.FindAll(x => x.parentId == parentId || x.parentId.IsNullOrEmpty());
|
||
|
||
// 移除父类对象
|
||
allNodes.RemoveAll(x => x.parentId == parentId || x.parentId.IsNullOrEmpty());
|
||
resData = rootNodes;
|
||
resData.ForEach(aRootNode =>
|
||
{
|
||
aRootNode.hasChildren = HaveChildren(allNodes, aRootNode.id);
|
||
if (aRootNode.hasChildren)
|
||
{
|
||
aRootNode.children = _GetChildren(allNodes, aRootNode);
|
||
aRootNode.num = aRootNode.children.Count();
|
||
}
|
||
else
|
||
{
|
||
aRootNode.isLeaf = !aRootNode.hasChildren;
|
||
aRootNode.children = null;
|
||
}
|
||
});
|
||
return resData;
|
||
}
|
||
|
||
|
||
|
||
#region 私有成员
|
||
|
||
/// <summary>
|
||
/// 获取所有子节点.
|
||
/// </summary>
|
||
/// <typeparam name="T">树模型(TreeModel或继承它的模型.</typeparam>
|
||
/// <param name="nodes">所有节点列表.</param>
|
||
/// <param name="parentNode">父节点Id.</param>
|
||
/// <returns></returns>
|
||
private static List<object> _GetChildren<T>(List<T> nodes, T parentNode)
|
||
where T : TreeModel, new()
|
||
{
|
||
Type type = typeof(T);
|
||
var properties = type.GetProperties().ToList();
|
||
List<object> resData = new List<object>();
|
||
|
||
// 查找出父类对象
|
||
var children = nodes.FindAll(x => x.parentId == parentNode.id);
|
||
|
||
// 移除父类对象
|
||
nodes.RemoveAll(x => x.parentId == parentNode.id);
|
||
children.ForEach(aChildren =>
|
||
{
|
||
T newNode = new T();
|
||
resData.Add(newNode);
|
||
|
||
// 赋值属性
|
||
foreach (var aProperty in properties.Where(x => x.CanWrite))
|
||
{
|
||
var value = aProperty.GetValue(aChildren, null);
|
||
aProperty.SetValue(newNode, value);
|
||
}
|
||
|
||
newNode.hasChildren = HaveChildren(nodes, aChildren.id);
|
||
if (newNode.hasChildren)
|
||
{
|
||
newNode.children = _GetChildren(nodes, newNode);
|
||
}
|
||
else
|
||
{
|
||
newNode.isLeaf = !newNode.hasChildren;
|
||
newNode.children = null;
|
||
}
|
||
});
|
||
return resData;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断当前节点是否有子节点.
|
||
/// </summary>
|
||
/// <typeparam name="T">树模型.</typeparam>
|
||
/// <param name="nodes">所有节点.</param>
|
||
/// <param name="nodeId">当前节点Id.</param>
|
||
/// <returns></returns>
|
||
private static bool HaveChildren<T>(List<T> nodes, string nodeId)
|
||
where T : TreeModel, new()
|
||
{
|
||
return nodes.Exists(x => x.parentId == nodeId);
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 树模型基类.
|
||
/// </summary>
|
||
public class TreeModel
|
||
{
|
||
/// <summary>
|
||
/// 获取节点id.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public string id { get; set; }
|
||
|
||
/// <summary>
|
||
/// 获取节点父id.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public string parentId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否有子级.
|
||
/// </summary>
|
||
public bool hasChildren { get; set; }
|
||
|
||
/// <summary>
|
||
/// 设置Children.
|
||
/// </summary>
|
||
public List<object>? children { get; set; } = new List<object>();
|
||
|
||
/// <summary>
|
||
/// 子节点数量.
|
||
/// </summary>
|
||
public int num { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否为子节点.
|
||
/// </summary>
|
||
public bool isLeaf { get; set; } = false;
|
||
} |