TreeExtensions.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using Masuit.Tools.Reflection;
  7. namespace Masuit.Tools.Models
  8. {
  9. /// <summary>
  10. /// 树形数据扩展
  11. /// </summary>
  12. public static class TreeExtensions
  13. {
  14. /// <summary>
  15. /// 过滤
  16. /// </summary>
  17. /// <typeparam name="T"></typeparam>
  18. /// <param name="items"></param>
  19. /// <param name="func"></param>
  20. /// <returns></returns>
  21. public static IEnumerable<T> Filter<T>(this IEnumerable<T> items, Func<T, bool> func) where T : class, ITreeChildren<T>
  22. {
  23. foreach (var item in items.Where(i => i != null))
  24. {
  25. item.Children ??= new List<T>();
  26. item.Children = item.Children.Filter(func).ToList();
  27. if (item.Children.Any() || func(item))
  28. {
  29. yield return item;
  30. }
  31. }
  32. }
  33. /// <summary>
  34. /// 过滤
  35. /// </summary>
  36. /// <typeparam name="T"></typeparam>
  37. /// <param name="items"></param>
  38. /// <param name="func"></param>
  39. /// <returns></returns>
  40. public static IEnumerable<Tree<T>> Filter<T>(this IEnumerable<Tree<T>> items, Func<Tree<T>, bool> func) where T : class
  41. {
  42. foreach (var item in items.Where(i => i != null))
  43. {
  44. item.Children ??= new List<Tree<T>>();
  45. item.Children = item.Children.Filter(func).ToList();
  46. if (item.Children.Any() || func(item))
  47. {
  48. yield return item;
  49. }
  50. }
  51. }
  52. /// <summary>
  53. /// 过滤
  54. /// </summary>
  55. /// <typeparam name="T"></typeparam>
  56. /// <param name="item"></param>
  57. /// <param name="func"></param>
  58. /// <returns></returns>
  59. public static IEnumerable<T> Filter<T>(this T item, Func<T, bool> func) where T : class, ITreeChildren<T>
  60. {
  61. return new[] { item }.Filter(func);
  62. }
  63. /// <summary>
  64. /// 过滤
  65. /// </summary>
  66. /// <typeparam name="T"></typeparam>
  67. /// <param name="item"></param>
  68. /// <param name="func"></param>
  69. /// <returns></returns>
  70. public static IEnumerable<Tree<T>> Filter<T>(this Tree<T> item, Func<Tree<T>, bool> func) where T : class
  71. {
  72. return new[] { item }.Filter(func);
  73. }
  74. /// <summary>
  75. /// 平铺开
  76. /// </summary>
  77. /// <typeparam name="T"></typeparam>
  78. /// <param name="items"></param>
  79. /// <param name="optionAction">平铺时子级需要做的操作,参数1:子级对象,参数2:父级对象</param>
  80. /// <returns></returns>
  81. public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items, Action<T, T> optionAction = null) where T : class, ITreeChildren<T>
  82. {
  83. foreach (var item in items)
  84. {
  85. yield return item;
  86. item.Children ??= new List<T>();
  87. item.Children.ForEach(c => optionAction?.Invoke(c, item));
  88. foreach (var children in item.Children.Flatten(optionAction))
  89. {
  90. yield return children;
  91. }
  92. }
  93. }
  94. /// <summary>
  95. /// 平铺开
  96. /// </summary>
  97. /// <typeparam name="T"></typeparam>
  98. /// <param name="p"></param>
  99. /// <param name="optionAction">平铺时子级需要做的操作,参数1:子级对象,参数2:父级对象</param>
  100. /// <returns></returns>
  101. public static IEnumerable<T> Flatten<T>(this T p, Action<T, T> optionAction = null) where T : class, ITreeChildren<T>
  102. {
  103. yield return p;
  104. foreach (var item in p.Children)
  105. {
  106. yield return item;
  107. item.Children ??= new List<T>();
  108. item.Children.ForEach(c => optionAction?.Invoke(c, item));
  109. foreach (var children in item.Children.Flatten())
  110. {
  111. yield return children;
  112. }
  113. }
  114. }
  115. /// <summary>
  116. /// 平铺开任意树形结构数据
  117. /// </summary>
  118. /// <typeparam name="T"></typeparam>
  119. /// <param name="items"></param>
  120. /// <param name="selector"></param>
  121. /// <param name="optionAction">平铺时子级需要做的操作,参数1:子级对象,参数2:父级对象</param>
  122. /// <returns></returns>
  123. public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector, Action<T, T> optionAction = null)
  124. {
  125. foreach (var item in items)
  126. {
  127. yield return item;
  128. selector(item).ForEach(c => optionAction?.Invoke(c, item));
  129. foreach (var children in selector(item).Flatten(selector))
  130. {
  131. yield return children;
  132. }
  133. }
  134. }
  135. /// <summary>
  136. /// 平铺开
  137. /// </summary>
  138. /// <typeparam name="T"></typeparam>
  139. /// <param name="items"></param>
  140. /// <param name="optionAction">平铺时子级需要做的操作,参数1:子级对象,参数2:父级对象</param>
  141. /// <returns></returns>
  142. public static IEnumerable<Tree<T>> Flatten<T>(this IEnumerable<Tree<T>> items, Action<Tree<T>, Tree<T>> optionAction = null) where T : class
  143. {
  144. foreach (var item in items)
  145. {
  146. yield return item;
  147. item.Children ??= new List<Tree<T>>();
  148. item.Children.ForEach(c => optionAction?.Invoke(c, item));
  149. foreach (var tree in item.Children.Flatten())
  150. {
  151. yield return tree;
  152. }
  153. }
  154. }
  155. /// <summary>
  156. /// 平铺开
  157. /// </summary>
  158. /// <typeparam name="T"></typeparam>
  159. /// <param name="p"></param>
  160. /// <param name="optionAction">平铺时子级需要做的操作,参数1:子级对象,参数2:父级对象</param>
  161. /// <returns></returns>
  162. public static IEnumerable<Tree<T>> Flatten<T>(this Tree<T> p, Action<Tree<T>, Tree<T>> optionAction = null) where T : class
  163. {
  164. yield return p;
  165. foreach (var item in p.Children)
  166. {
  167. yield return item;
  168. item.Children ??= new List<Tree<T>>();
  169. item.Children.ForEach(c => optionAction?.Invoke(c, item));
  170. foreach (var tree in item.Children.Flatten())
  171. {
  172. yield return tree;
  173. }
  174. }
  175. }
  176. /// <summary>
  177. /// 平铺开任意树形结构数据
  178. /// </summary>
  179. /// <typeparam name="T"></typeparam>
  180. /// <param name="items"></param>
  181. /// <param name="selector"></param>
  182. /// <param name="optionAction">平铺时子级需要做的操作,参数1:子级对象,参数2:父级对象</param>
  183. /// <returns></returns>
  184. public static IEnumerable<Tree<T>> Flatten<T>(this IEnumerable<Tree<T>> items, Func<Tree<T>, IEnumerable<Tree<T>>> selector, Action<Tree<T>, Tree<T>> optionAction = null)
  185. {
  186. foreach (var item in items)
  187. {
  188. yield return item;
  189. item.Children.ForEach(c => optionAction?.Invoke(c, item));
  190. foreach (var tree in selector(item).Flatten(selector))
  191. {
  192. yield return tree;
  193. }
  194. }
  195. }
  196. /// <summary>
  197. /// 平行集合转换成树形结构
  198. /// </summary>
  199. /// <typeparam name="T"></typeparam>
  200. /// <param name="source"></param>
  201. /// <param name="idSelector"></param>
  202. /// <param name="pidSelector"></param>
  203. /// <param name="topValue">根对象parentId的值</param>
  204. /// <returns></returns>
  205. public static List<T> ToTree<T>(this IEnumerable<T> source, Expression<Func<T, string>> idSelector, Expression<Func<T, string>> pidSelector, string topValue = default) where T : ITreeParent<T>, ITreeChildren<T>
  206. {
  207. return ToTree<T, string>(source, idSelector, pidSelector, topValue);
  208. }
  209. /// <summary>
  210. /// 平行集合转换成树形结构
  211. /// </summary>
  212. /// <typeparam name="T"></typeparam>
  213. /// <param name="source"></param>
  214. /// <param name="idSelector"></param>
  215. /// <param name="pidSelector"></param>
  216. /// <param name="topValue">根对象parentId的值</param>
  217. /// <returns></returns>
  218. public static List<T> ToTree<T>(this IEnumerable<T> source, Expression<Func<T, int>> idSelector, Expression<Func<T, int>> pidSelector, int topValue = 0) where T : ITreeParent<T>, ITreeChildren<T>
  219. {
  220. return ToTree<T, int>(source, idSelector, pidSelector, topValue);
  221. }
  222. /// <summary>
  223. /// 平行集合转换成树形结构
  224. /// </summary>
  225. /// <typeparam name="T"></typeparam>
  226. /// <param name="source"></param>
  227. /// <param name="idSelector"></param>
  228. /// <param name="pidSelector"></param>
  229. /// <param name="topValue">根对象parentId的值</param>
  230. /// <returns></returns>
  231. public static List<T> ToTree<T>(this IEnumerable<T> source, Expression<Func<T, long>> idSelector, Expression<Func<T, long>> pidSelector, long topValue = 0) where T : ITreeParent<T>, ITreeChildren<T>
  232. {
  233. return ToTree<T, long>(source, idSelector, pidSelector, topValue);
  234. }
  235. /// <summary>
  236. /// 平行集合转换成树形结构
  237. /// </summary>
  238. /// <typeparam name="T"></typeparam>
  239. /// <param name="source"></param>
  240. /// <param name="idSelector"></param>
  241. /// <param name="pidSelector"></param>
  242. /// <param name="topValue">根对象parentId的值</param>
  243. /// <returns></returns>
  244. public static List<T> ToTree<T>(this IEnumerable<T> source, Expression<Func<T, Guid>> idSelector, Expression<Func<T, Guid>> pidSelector, Guid topValue = default) where T : ITreeParent<T>, ITreeChildren<T>
  245. {
  246. return ToTree<T, Guid>(source, idSelector, pidSelector, topValue);
  247. }
  248. /// <summary>
  249. /// 平行集合转换成树形结构
  250. /// </summary>
  251. /// <typeparam name="T"></typeparam>
  252. /// <typeparam name="TKey"></typeparam>
  253. /// <param name="source"></param>
  254. /// <param name="idSelector"></param>
  255. /// <param name="pidSelector"></param>
  256. /// <param name="topValue">根对象parentId的值</param>
  257. /// <returns></returns>
  258. public static List<T> ToTree<T, TKey>(this IEnumerable<T> source, Expression<Func<T, TKey>> idSelector, Expression<Func<T, TKey>> pidSelector, TKey topValue = default) where T : ITreeParent<T>, ITreeChildren<T> where TKey : IComparable
  259. {
  260. if (source is IQueryable<T> queryable)
  261. {
  262. source = queryable.ToList();
  263. }
  264. if (idSelector.Body.ToString() == pidSelector.Body.ToString())
  265. {
  266. throw new ArgumentException("idSelector和pidSelector不应该为同一字段!");
  267. }
  268. var pidFunc = pidSelector.Compile();
  269. var idFunc = idSelector.Compile();
  270. source = source.Where(t => t != null);
  271. var temp = new List<T>();
  272. foreach (var item in source.Where(item => pidFunc(item) is null || pidFunc(item).Equals(topValue)))
  273. {
  274. item.Parent = default;
  275. TransData(source, item, idFunc, pidFunc);
  276. temp.Add(item);
  277. }
  278. return temp;
  279. }
  280. /// <summary>
  281. /// 平行集合转换成树形结构
  282. /// </summary>
  283. /// <typeparam name="T"></typeparam>
  284. /// <param name="source"></param>
  285. /// <returns></returns>
  286. public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T, int>
  287. {
  288. return ToTree<T, int>(source);
  289. }
  290. /// <summary>
  291. /// 平行集合转换成树形结构
  292. /// </summary>
  293. /// <typeparam name="T"></typeparam>
  294. /// <typeparam name="TKey"></typeparam>
  295. /// <param name="source"></param>
  296. /// <returns></returns>
  297. public static List<T> ToTree<T, TKey>(this IEnumerable<T> source) where T : ITreeEntity<T, TKey> where TKey : struct, IComparable
  298. {
  299. if (source is IQueryable<T> queryable)
  300. {
  301. source = queryable.ToList();
  302. }
  303. source = source.Where(t => t != null);
  304. var temp = new List<T>();
  305. foreach (var item in source.Where(item => item.ParentId is null || item.ParentId.Equals(default)))
  306. {
  307. TransData<T, TKey>(source, item);
  308. temp.Add(item);
  309. }
  310. return temp;
  311. }
  312. /// <summary>
  313. /// 平行集合转换成树形结构
  314. /// </summary>
  315. /// <typeparam name="T"></typeparam>
  316. /// <typeparam name="TKey"></typeparam>
  317. /// <param name="source"></param>
  318. /// <param name="idSelector"></param>
  319. /// <param name="pidSelector"></param>
  320. /// <param name="topValue">根对象parentId的值</param>
  321. /// <returns></returns>
  322. public static List<T> ToTree<T, TKey>(this IEnumerable<T> source, Expression<Func<T, TKey>> idSelector, Expression<Func<T, TKey?>> pidSelector, TKey? topValue = default) where T : ITreeChildren<T> where TKey : struct
  323. {
  324. if (source is IQueryable<T> queryable)
  325. {
  326. source = queryable.ToList();
  327. }
  328. var pidFunc = pidSelector.Compile();
  329. var idFunc = idSelector.Compile();
  330. source = source.Where(t => t != null);
  331. var temp = new List<T>();
  332. foreach (var item in source.Where(item => pidFunc(item) is null || pidFunc(item).Equals(topValue)))
  333. {
  334. TransData(source, item, idFunc, pidFunc);
  335. temp.Add(item);
  336. }
  337. return temp;
  338. }
  339. private static void TransData<T, TKey>(IEnumerable<T> source, T parent, Func<T, TKey> idSelector, Func<T, TKey> pidSelector) where T : ITreeChildren<T> where TKey : IComparable
  340. {
  341. var temp = new List<T>();
  342. foreach (var item in source.Where(item => pidSelector(item)?.Equals(idSelector(parent)) == true))
  343. {
  344. TransData(source, item, idSelector, pidSelector);
  345. if (item is ITreeParent<T> c)
  346. {
  347. c.Parent = parent;
  348. }
  349. temp.Add(item);
  350. }
  351. parent.Children = temp;
  352. }
  353. internal static void TransData<T, TKey>(IEnumerable<T> source, T parent) where T : ITreeEntity<T, TKey> where TKey : struct, IComparable
  354. {
  355. var temp = new List<T>();
  356. foreach (var item in source.Where(item => item.ParentId?.Equals(parent.Id) == true))
  357. {
  358. TransData<T, TKey>(source, item);
  359. if (item is ITreeParent<T> c)
  360. {
  361. c.Parent = parent;
  362. }
  363. temp.Add(item);
  364. }
  365. parent.Children = temp;
  366. }
  367. internal static void TransData<T>(IEnumerable<T> source, T parent) where T : ITreeEntity<T>
  368. {
  369. var temp = new List<T>();
  370. foreach (var item in source.Where(item => item.ParentId?.Equals(parent.Id) == true))
  371. {
  372. TransData(source, item);
  373. if (item is ITreeParent<T> c)
  374. {
  375. c.Parent = parent;
  376. }
  377. temp.Add(item);
  378. }
  379. parent.Children = temp;
  380. }
  381. private static void TransData<T, TKey>(IEnumerable<T> source, T parent, Func<T, TKey> idSelector, Func<T, TKey?> pidSelector) where T : ITreeChildren<T> where TKey : struct
  382. {
  383. var temp = new List<T>();
  384. foreach (var item in source.Where(item => pidSelector(item)?.Equals(idSelector(parent)) == true))
  385. {
  386. TransData(source, item, idSelector, pidSelector);
  387. if (item is ITreeParent<T> c)
  388. {
  389. c.Parent = parent;
  390. }
  391. temp.Add(item);
  392. }
  393. parent.Children = temp;
  394. }
  395. /// <summary>
  396. /// 平行集合转换成树形结构
  397. /// </summary>
  398. /// <typeparam name="T"></typeparam>
  399. /// <typeparam name="TKey"></typeparam>
  400. /// <param name="source"></param>
  401. /// <param name="idSelector"></param>
  402. /// <param name="pidSelector"></param>
  403. /// <param name="topValue">根对象parentId的值</param>
  404. /// <returns></returns>
  405. public static List<Tree<T>> ToTreeGeneral<T, TKey>(this IEnumerable<T> source, Expression<Func<T, TKey>> idSelector, Expression<Func<T, TKey>> pidSelector, TKey topValue = default) where TKey : IComparable
  406. {
  407. if (idSelector.Body.ToString() == pidSelector.Body.ToString())
  408. {
  409. throw new ArgumentException("idSelector和pidSelector不应该为同一字段!");
  410. }
  411. var pidFunc = pidSelector.Compile();
  412. var idFunc = idSelector.Compile();
  413. source = source.Where(t => t != null);
  414. var temp = new List<Tree<T>>();
  415. foreach (var item in source.Where(item => pidFunc(item) is null || pidFunc(item).Equals(topValue)))
  416. {
  417. var parent = new Tree<T>(item);
  418. TransData(source, parent, idFunc, pidFunc);
  419. temp.Add(parent);
  420. }
  421. return temp;
  422. }
  423. private static void TransData<T, TKey>(IEnumerable<T> source, Tree<T> parent, Func<T, TKey> idSelector, Func<T, TKey> pidSelector) where TKey : IComparable
  424. {
  425. var temp = new List<Tree<T>>();
  426. foreach (var item in source.Where(item => pidSelector(item)?.Equals(idSelector(parent.Value)) == true))
  427. {
  428. var p = new Tree<T>(item);
  429. TransData(source, p, idSelector, pidSelector);
  430. p.Parent = parent.Value;
  431. temp.Add(p);
  432. }
  433. parent.Children = temp;
  434. }
  435. /// <summary>
  436. /// 所有子级
  437. /// </summary>
  438. public static ICollection<T> AllChildren<T>(this T tree) where T : ITreeChildren<T> => GetChildren(tree, c => c.Children);
  439. /// <summary>
  440. /// 所有子级
  441. /// </summary>
  442. public static ICollection<T> AllChildren<T>(this T tree, Func<T, IEnumerable<T>> selector) where T : ITreeChildren<T> => GetChildren(tree, selector);
  443. /// <summary>
  444. /// 所有子级
  445. /// </summary>
  446. public static ICollection<Tree<T>> AllChildren<T>(this Tree<T> tree) => GetChildren(tree, c => c.Children);
  447. /// <summary>
  448. /// 所有子级
  449. /// </summary>
  450. public static ICollection<Tree<T>> AllChildren<T>(this Tree<T> tree, Func<Tree<T>, IEnumerable<Tree<T>>> selector) => GetChildren(tree, selector);
  451. /// <summary>
  452. /// 所有父级
  453. /// </summary>
  454. public static ICollection<T> AllParent<T>(this T tree) where T : ITreeParent<T> => GetParents(tree, c => c.Parent);
  455. /// <summary>
  456. /// 所有父级
  457. /// </summary>
  458. public static ICollection<T> AllParent<T>(this T tree, Func<T, T> selector) where T : ITreeParent<T> => GetParents(tree, selector);
  459. /// <summary>
  460. /// 所有父级
  461. /// </summary>
  462. public static ICollection<Tree<T>> AllParent<T>(this Tree<T> tree, Func<Tree<T>, Tree<T>> selector) => GetParents(tree, selector);
  463. /// <summary>
  464. /// 是否是根节点
  465. /// </summary>
  466. public static bool IsRoot<T>(this ITreeParent<T> tree) where T : ITreeParent<T> => tree.Parent == null;
  467. /// <summary>
  468. /// 是否是叶子节点
  469. /// </summary>
  470. public static bool IsLeaf<T>(this ITreeChildren<T> tree) where T : ITreeChildren<T> => tree.Children?.Count == 0;
  471. /// <summary>
  472. /// 是否是根节点
  473. /// </summary>
  474. public static bool IsRoot<T>(this Tree<T> tree) => tree.Parent == null;
  475. /// <summary>
  476. /// 是否是叶子节点
  477. /// </summary>
  478. public static bool IsLeaf<T>(this Tree<T> tree) => tree.Children?.Count == 0;
  479. /// <summary>
  480. /// 深度层级
  481. /// </summary>
  482. public static int Level<T>(this ITreeParent<T> tree) where T : ITreeParent<T> => IsRoot(tree) ? 1 : Level(tree.Parent) + 1;
  483. /// <summary>
  484. /// 节点路径(UNIX路径格式,以“/”分隔)
  485. /// </summary>
  486. public static string Path<T>(this T tree) where T : ITree<T> => GetFullPath(tree, t => t.Name);
  487. /// <summary>
  488. /// 节点路径(UNIX路径格式,以“/”分隔)
  489. /// </summary>
  490. public static string Path<T>(this T tree, Func<T, string> selector) where T : ITreeParent<T> => GetFullPath(tree, selector);
  491. /// <summary>
  492. /// 节点路径
  493. /// </summary>
  494. /// <param name="tree"></param>
  495. /// <param name="separator">分隔符</param>
  496. public static string Path<T>(this T tree, string separator) where T : ITree<T> => GetFullPath(tree, t => t.Name, separator);
  497. /// <summary>
  498. /// 节点路径
  499. /// </summary>
  500. /// <typeparam name="T"></typeparam>
  501. /// <param name="tree"></param>
  502. /// <param name="selector">选择字段</param>
  503. /// <param name="separator">分隔符</param>
  504. /// <returns></returns>
  505. public static string Path<T>(this T tree, Func<T, string> selector, string separator) where T : ITreeParent<T> => GetFullPath(tree, selector, separator);
  506. /// <summary>
  507. /// 根节点
  508. /// </summary>
  509. public static T Root<T>(this T tree) where T : ITreeParent<T> => GetRoot(tree, t => t.Parent);
  510. private static string GetFullPath<T>(T c, Func<T, string> selector, string separator = "/") where T : ITreeParent<T> => c.Parent != null ? GetFullPath(c.Parent, selector, separator) + separator + selector(c) : selector(c);
  511. /// <summary>
  512. /// 根节点
  513. /// </summary>
  514. public static T GetRoot<T>(T c, Func<T, T> selector) where T : ITreeParent<T> => c.Parent != null ? GetRoot(c.Parent, selector) : c;
  515. /// <summary>
  516. /// 递归取出所有下级
  517. /// </summary>
  518. /// <param name="t"></param>
  519. /// <param name="selector"></param>
  520. /// <returns></returns>
  521. private static List<T> GetChildren<T>(T t, Func<T, IEnumerable<T>> selector)
  522. {
  523. return selector(t).Union(selector(t).Where(c => selector(c)?.Any() == true).SelectMany(c => GetChildren(c, selector))).ToList();
  524. }
  525. /// <summary>
  526. /// 递归取出所有上级
  527. /// </summary>
  528. /// <param name="t"></param>
  529. /// <returns></returns>
  530. private static List<T> GetParents<T>(T t, Func<T, T> selector)
  531. {
  532. var list = new List<T>() { selector(t) };
  533. if (selector(t) != null)
  534. {
  535. return list.Union(GetParents(selector(t), selector)).Where(x => x != null).ToList();
  536. }
  537. list.RemoveAll(x => x == null);
  538. return list;
  539. }
  540. }
  541. public static class TreeExtensionLong
  542. {
  543. /// <summary>
  544. /// 平行集合转换成树形结构
  545. /// </summary>
  546. /// <typeparam name="T"></typeparam>
  547. /// <param name="source"></param>
  548. /// <returns></returns>
  549. public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T, long>
  550. {
  551. return source.ToTree<T, long>();
  552. }
  553. }
  554. public static class TreeExtensionGuid
  555. {
  556. /// <summary>
  557. /// 平行集合转换成树形结构
  558. /// </summary>
  559. /// <typeparam name="T"></typeparam>
  560. /// <param name="source"></param>
  561. /// <returns></returns>
  562. public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T, Guid>
  563. {
  564. return source.ToTree<T, Guid>();
  565. }
  566. }
  567. public static class TreeExtensionString
  568. {
  569. /// <summary>
  570. /// 平行集合转换成树形结构
  571. /// </summary>
  572. /// <typeparam name="T"></typeparam>
  573. /// <param name="source"></param>
  574. /// <returns></returns>
  575. public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T>
  576. {
  577. if (source is IQueryable<T> queryable)
  578. {
  579. source = queryable.ToList();
  580. }
  581. source = source.Where(t => t != null);
  582. var temp = new List<T>();
  583. foreach (var item in source.Where(item => item.ParentId is null || item.ParentId.Equals(default)))
  584. {
  585. TreeExtensions.TransData(source, item);
  586. temp.Add(item);
  587. }
  588. return temp;
  589. }
  590. }
  591. }