用途
将任意层级的对象,例如下面这个
public class Dept {
public Dept(string name) { this.name = name; }
public string name;
public List<Dept> child;
public List<Team> team;
public List<Person> person;
public override string ToString() {
return $"Dept({name})";
}
}
public class Team {
public Team(string name) { this.name = name; }
public string name;
public List<Team> child;
public List<Person> person;
public override string ToString() {
return $"Team({name})";
}
}
public class Person {
public Person(string name) { this.name = name; }
public string name;
public override string ToString() {
return $"Person({name})";
}
}
转换为单一的树形对象,例如下面这个
public class Label {
public Label(string text) { this.text = text; }
public string text;
public List<Label> child;
}
调用方法举例:
var listDept = new List<Dept>();
var dept = new Dept("AA部门") {
child = new List<Dept>() {
new Dept("BB部门") {
person=new List<Person>(){ new Person("赵"), new Person("钱"), new Person("孙") },
child=new List<Dept>() {
new Dept("CC部门") {
team=new List<Team>() {
new Team("开发") {
child=new List<Team>() {
new Team("前端") {
person=new List<Person>() { new Person("李"), new Person("周") }
},
new Team("后端") {
person=new List<Person>() { new Person("吴"), new Person("郑") }
}
},
person=new List<Person>() { new Person("王") }
},
new Team("运维"),
}
},
new Dept("DD部门")
}
}
}
};
listDept.Add(dept);
List<Label> list = TreeNode<Label>.ConvertList(listDept,
// 设置子列表
t => t.child ?? (t.child = new List<Label>()),
// 所有类型转换定义
new Dictionary<Type, Func<object, TreeNode<Label>>>() {
{ typeof(Dept), t=>new TreeNode<Label>(new Label(t.ToString())) },
{ typeof(Team), t=>new TreeNode<Label>(new Label(t.ToString())) },
{ typeof(Person), t=>new TreeNode<Label>(new Label(t.ToString())) },
},
// 所有类型子列表定义
new Dictionary<Type, Func<object, IList[]>>() {
{ typeof(Dept), t=>new IList[]{ ((Dept)t).child, ((Dept)t).person, ((Dept)t).team } },
{ typeof(Team), t=>new IList[]{ ((Team)t).child, ((Team)t).person } },
}
);
Console.WriteLine(list.toJSON());
输出结果:
[
{
"text": "Dept(AA部门)",
"child": [
{
"text": "Dept(BB部门)",
"child": [
{
"text": "Dept(CC部门)",
"child": [
{
"text": "Team(开发)",
"child": [
{
"text": "Team(前端)",
"child": [
{
"text": "Person(李)",
"child": null
},
{
"text": "Person(周)",
"child": null
}
]
},
{
"text": "Team(后端)",
"child": [
{
"text": "Person(吴)",
"child": null
},
{
"text": "Person(郑)",
"child": null
}
]
},
{
"text": "Person(王)",
"child": null
}
]
},
{
"text": "Team(运维)",
"child": null
}
]
},
{
"text": "Dept(DD部门)",
"child": null
},
{
"text": "Person(赵)",
"child": null
},
{
"text": "Person(钱)",
"child": null
},
{
"text": "Person(孙)",
"child": null
}
]
}
]
}
]
工具类:
using System;
using System.Collections;
using System.Collections.Generic;
namespace Ccino.Lib {
public class TreeNode<T> {
public TreeNode(T item) {
this.item = item;
}
/// <summary>
/// 挂载对象
/// </summary>
public T item;
/// <summary>
/// 原始对象
/// </summary>
[Newtonsoft.Json.JsonIgnore]
public object sourceItem;
/// <summary>
/// 子列表
/// </summary>
public List<TreeNode<T>> children;
/// <summary>
/// 父对象
/// </summary>
[Newtonsoft.Json.JsonIgnore]
public TreeNode<T> parent;
/// <summary>
/// 将TreeNode列表转换为目标类型列表
/// </summary>
/// <typeparam name="E">目标类型</typeparam>
/// <param name="listNode">TreeNode列表</param>
/// <param name="convertAction">转换方法</param>
/// <param name="getChildList">子列表获取/处理</param>
public static List<E> ConvertTo<E>(List<TreeNode<T>> listNode, Func<TreeNode<T>, E> convertAction, Func<E, List<E>> getChildList) {
List<E> list = new List<E>();
foreach (var node in listNode) {
E e = convertAction(node);
// 处理当前列表
if (e != null) {
list.Add(e);
}
// 处理子列表
if (node.children != null) {
var childList = getChildList(e);
childList.AddRange(ConvertTo<E>(node.children, convertAction, getChildList));
}
}
return list;
}
/// <summary>
/// 转换树形对象
/// </summary>
/// <param name="sourceTree">原始树列表</param>
/// <param name="getSetChildList">原始数对象子列表获取/设置</param>
/// <param name="convertActionDict">类型转换字典,定义可被转换为TreeNode的类型</param>
/// <param name="getChildListDict">子列表获取字典, 定义需要处理的类型子列表</param>
public static List<T> ConvertList(IList sourceTree, Func<T, List<T>> getSetChildList,
Dictionary<Type, Func<object, TreeNode<T>>> convertActionDict,
Dictionary<Type, Func<object, IList[]>> getChildListDict) {
var nodeList = ConvertTreeNode(sourceTree, convertActionDict, getChildListDict);
return ConvertTo<T>(nodeList, node => node.item, getSetChildList);
}
/// <summary>
/// 转换树形对象
/// </summary>
/// <param name="sourceTree">原始树列表</param>
/// <param name="convertActionDict">类型转换字典,定义可被转换为TreeNode的类型</param>
/// <param name="getChildListDict">子列表获取字典, 定义需要处理的类型子列表</param>
public static List<TreeNode<T>> ConvertTreeNode(IList sourceTree,
Dictionary<Type, Func<object, TreeNode<T>>> convertActionDict,
Dictionary<Type, Func<object, IList[]>> getChildListDict) {
List<TreeNode<T>> resultList = new List<TreeNode<T>>();
Func<object, TreeNode<T>> convertTAction = null;
#region 获得转换原始对象方法
if (sourceTree.Count > 0) {
var type = sourceTree[0].GetType();
if (!convertActionDict.TryGetValue(type, out convertTAction)) {
Console.WriteLine(type + " " + convertTAction);
return resultList;
}
} else {
return resultList;
}
#endregion
for (int i = 0, len = sourceTree.Count; i < len; ++i) {
object sourceItem = sourceTree[i];
//1. 处理原始对象转换
TreeNode<T> currentNode = null;
currentNode = convertTAction(sourceItem);
if (currentNode == null) continue; //如果无法转换node,直接跳过
currentNode.sourceItem = sourceItem; //记录原始对象
resultList.Add(currentNode);
//2. 处理所有子列表转换
Type sourceType = sourceItem.GetType();
foreach (var kv in getChildListDict) {
Type type = kv.Key;
if (sourceType != type) continue;
Func<object, IList[]> getListAction = kv.Value;
IList[] lists = getListAction(sourceItem);
if (lists != null && lists.Length > 0) {
foreach (var list in lists) {
if (list != null && list.Count > 0) {
var listNode = ConvertTreeNode(list, convertActionDict, getChildListDict);
if (listNode.Count > 0) {
if (currentNode.children == null) {
currentNode.children = new List<TreeNode<T>>();
}
listNode.ForEach(n => {
n.parent = currentNode;
currentNode.children.Add(n);
});
}
}
}
}
}
}
return resultList;
}
}
}