2021-09-09 C# 任意类型任意多个子列表对象转换为标准树形对象【工具类】

用途

将任意层级的对象,例如下面这个

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

  }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值