Browse Source

1.支持.NET8
2.树形结构增强
3.EFCore的AddOrUpdate扩展增强

懒得勤快 1 year ago
parent
commit
812b82ed3e

+ 13 - 8
Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj

@@ -1,11 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
-        <TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5;net6;net7</TargetFrameworks>
+        <TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5;net6;net7;net8</TargetFrameworks>
         <LangVersion>latest</LangVersion>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
         <Version>2.6.7.5</Version>
         <Authors>懒得勤快</Authors>
-        <Description>新手友好的C#万能工具库,码数吐司库,Masuit.Tools基础公共库(适用于.NET4.6.1/.NET Standard2.0及以上项目),包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。
+        <Description>全龄段友好的C#万能工具库,码数吐司库,不管你是菜鸟新手还是骨灰级玩家都能轻松上手,Masuit.Tools基础公共库(适用于.NET4.6.1/.NET Standard2.0及以上项目),包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。
             官网教程:https://tools.masuit.org
             github:https://github.com/ldqk/Masuit.Tools
         </Description>
@@ -46,18 +46,18 @@
     </ItemGroup>
 
     <ItemGroup>
-        <PackageReference Include="AngleSharp" Version="1.0.6-alpha-325" />
+        <PackageReference Include="AngleSharp" Version="1.0.6" />
         <PackageReference Include="AngleSharp.Css" Version="1.0.0-alpha-99" />
         <PackageReference Include="Castle.Core" Version="5.1.1" />
         <PackageReference Include="DnsClient" Version="1.7.0" />
         <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
-        <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
+        <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
         <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
-        <PackageReference Include="System.Collections.Immutable" Version="7.0.0" />
-        <PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
-        <PackageReference Include="System.Management" Version="7.0.2" />
+        <PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
+        <PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />
+        <PackageReference Include="System.Management" Version="8.0" />
         <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
-        <PackageReference Include="SharpCompress" Version="0.34.1" />
+        <PackageReference Include="SharpCompress" Version="0.34.2" />
     </ItemGroup>
 
     <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
@@ -87,6 +87,11 @@
         <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.0.1" />
     </ItemGroup>
 
+    <ItemGroup Condition=" '$(TargetFramework)' == 'net8'">
+        <PackageReference Include="System.Diagnostics.PerformanceCounter" Version="8.0.0" />
+        <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.0.1" />
+    </ItemGroup>
+
     <ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
         <Reference Include="System.Web" />
         <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="[1.0.0]" />

+ 17 - 2
Masuit.Tools.Abstractions/Models/ITree.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 
 namespace Masuit.Tools.Models
 {
@@ -37,4 +38,18 @@ namespace Masuit.Tools.Models
         /// </summary>
         T Parent { get; set; }
     }
-}
+
+    public interface ITreeEntity<T, TKey> : ITreeChildren<T> where TKey : struct, IComparable
+    {
+        public TKey Id { get; set; }
+
+        public TKey? ParentId { get; set; }
+    }
+
+    public interface ITreeEntity<T> : ITreeChildren<T>
+    {
+        public string Id { get; set; }
+
+        public string ParentId { get; set; }
+    }
+}

+ 143 - 8
Masuit.Tools.Abstractions/Models/TreeExtensions.cs

@@ -1,7 +1,9 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Linq;
 using System.Linq.Expressions;
+using Masuit.Tools.Reflection;
 
 namespace Masuit.Tools.Models
 {
@@ -270,6 +272,11 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         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
         {
+            if (source is IQueryable<T> queryable)
+            {
+                source = queryable.ToList();
+            }
+
             if (idSelector.Body.ToString() == pidSelector.Body.ToString())
             {
                 throw new ArgumentException("idSelector和pidSelector不应该为同一字段!");
@@ -289,6 +296,42 @@ namespace Masuit.Tools.Models
             return temp;
         }
 
+        /// <summary>
+        /// 平行集合转换成树形结构
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T, int>
+        {
+            return ToTree<T, int>(source);
+        }
+
+        /// <summary>
+        /// 平行集合转换成树形结构
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <typeparam name="TKey"></typeparam>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static List<T> ToTree<T, TKey>(this IEnumerable<T> source) where T : ITreeEntity<T, TKey> where TKey : struct, IComparable
+        {
+            if (source is IQueryable<T> queryable)
+            {
+                source = queryable.ToList();
+            }
+
+            source = source.Where(t => t != null);
+            var temp = new List<T>();
+            foreach (var item in source.Where(item => item.ParentId is null || item.ParentId.Equals(default)))
+            {
+                TransData<T, TKey>(source, item);
+                temp.Add(item);
+            }
+
+            return temp;
+        }
+
         /// <summary>
         /// 平行集合转换成树形结构
         /// </summary>
@@ -299,11 +342,11 @@ namespace Masuit.Tools.Models
         /// <param name="pidSelector"></param>
         /// <param name="topValue">根对象parentId的值</param>
         /// <returns></returns>
-        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 : struct
+        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
         {
-            if (idSelector.Body.ToString() == pidSelector.Body.ToString())
+            if (source is IQueryable<T> queryable)
             {
-                throw new ArgumentException("idSelector和pidSelector不应该为同一字段!");
+                source = queryable.ToList();
             }
 
             var pidFunc = pidSelector.Compile();
@@ -312,7 +355,6 @@ namespace Masuit.Tools.Models
             var temp = new List<T>();
             foreach (var item in source.Where(item => pidFunc(item) is null || pidFunc(item).Equals(topValue)))
             {
-                item.Parent = default;
                 TransData(source, item, idFunc, pidFunc);
                 temp.Add(item);
             }
@@ -320,26 +362,64 @@ namespace Masuit.Tools.Models
             return temp;
         }
 
-        private static void TransData<T, TKey>(IEnumerable<T> source, T parent, Func<T, TKey> idSelector, Func<T, TKey> pidSelector) where T : ITreeParent<T>, ITreeChildren<T> where TKey : IComparable
+        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
         {
             var temp = new List<T>();
             foreach (var item in source.Where(item => pidSelector(item)?.Equals(idSelector(parent)) == true))
             {
                 TransData(source, item, idSelector, pidSelector);
-                item.Parent = parent;
+                if (item is ITreeParent<T> c)
+                {
+                    c.Parent = parent;
+                }
+                temp.Add(item);
+            }
+
+            parent.Children = temp;
+        }
+
+        internal static void TransData<T, TKey>(IEnumerable<T> source, T parent) where T : ITreeEntity<T, TKey> where TKey : struct, IComparable
+        {
+            var temp = new List<T>();
+            foreach (var item in source.Where(item => item.ParentId?.Equals(parent.Id) == true))
+            {
+                TransData<T, TKey>(source, item);
+                if (item is ITreeParent<T> c)
+                {
+                    c.Parent = parent;
+                }
+                temp.Add(item);
+            }
+
+            parent.Children = temp;
+        }
+
+        internal static void TransData<T>(IEnumerable<T> source, T parent) where T : ITreeEntity<T>
+        {
+            var temp = new List<T>();
+            foreach (var item in source.Where(item => item.ParentId?.Equals(parent.Id) == true))
+            {
+                TransData(source, item);
+                if (item is ITreeParent<T> c)
+                {
+                    c.Parent = parent;
+                }
                 temp.Add(item);
             }
 
             parent.Children = temp;
         }
 
-        private static void TransData<T, TKey>(IEnumerable<T> source, T parent, Func<T, TKey> idSelector, Func<T, TKey?> pidSelector) where T : ITreeParent<T>, ITreeChildren<T> where TKey : struct
+        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
         {
             var temp = new List<T>();
             foreach (var item in source.Where(item => pidSelector(item)?.Equals(idSelector(parent)) == true))
             {
                 TransData(source, item, idSelector, pidSelector);
-                item.Parent = parent;
+                if (item is ITreeParent<T> c)
+                {
+                    c.Parent = parent;
+                }
                 temp.Add(item);
             }
 
@@ -517,4 +597,59 @@ namespace Masuit.Tools.Models
             return list;
         }
     }
+
+    public static class TreeExtensionLong
+    {
+        /// <summary>
+        /// 平行集合转换成树形结构
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T, long>
+        {
+            return source.ToTree<T, long>();
+        }
+    }
+
+    public static class TreeExtensionGuid
+    {
+        /// <summary>
+        /// 平行集合转换成树形结构
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T, Guid>
+        {
+            return source.ToTree<T, Guid>();
+        }
+    }
+
+    public static class TreeExtensionString
+    {
+        /// <summary>
+        /// 平行集合转换成树形结构
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static List<T> ToTree<T>(this IEnumerable<T> source) where T : ITreeEntity<T>
+        {
+            if (source is IQueryable<T> queryable)
+            {
+                source = queryable.ToList();
+            }
+
+            source = source.Where(t => t != null);
+            var temp = new List<T>();
+            foreach (var item in source.Where(item => item.ParentId is null || item.ParentId.Equals(default)))
+            {
+                TreeExtensions.TransData(source, item);
+                temp.Add(item);
+            }
+
+            return temp;
+        }
+    }
 }

+ 5 - 0
Masuit.Tools.AspNetCore/AspNetCore/DbSetExtensions.cs

@@ -47,6 +47,11 @@ public static class DbSetExtensions
             collection = entities.ToList();
         }
 
+        if (collection.Count == 0)
+        {
+            return;
+        }
+
         var func = keySelector.CompileFast();
         var keyObjects = collection.Select(s => func(s)).ToList();
         var parameter = keySelector.Parameters[0];

+ 7 - 4
Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj

@@ -1,10 +1,10 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
     <PropertyGroup>
-        <TargetFrameworks>netcoreapp3.1;net5;net6;net7</TargetFrameworks>
+        <TargetFrameworks>netcoreapp3.1;net5;net6;net7;net8</TargetFrameworks>
         <ImplicitUsings>enable</ImplicitUsings>
         <Description>
-            新手友好的C#万能工具库,码数吐司库(适用于.NET Core Web项目),包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。包含一些AspNetCore常用的工具类、ModelBinder等。
+            全龄段友好的C#万能工具库,码数吐司库(适用于.NET Core Web项目),不管你是菜鸟新手还是骨灰级玩家都能轻松上手,包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。包含一些AspNetCore常用的工具类、ModelBinder等。
             官网教程:https://tools.masuit.org
             github:https://github.com/ldqk/Masuit.Tools
         </Description>
@@ -44,8 +44,8 @@
     </ItemGroup>
 
     <ItemGroup>
-      <PackageReference Include="FastExpressionCompiler" Version="3.3.4" />
-      <PackageReference Include="System.Net.Http.Json" Version="7.0.1" />
+      <PackageReference Include="FastExpressionCompiler" Version="4.0.0" />
+      <PackageReference Include="System.Net.Http.Json" Version="8.0" />
     </ItemGroup>
 
     <ItemGroup>
@@ -64,4 +64,7 @@
     <ItemGroup Condition=" '$(TargetFramework)' == 'net7'">
         <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.13" />
     </ItemGroup>
+    <ItemGroup Condition=" '$(TargetFramework)' == 'net8'">
+        <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0" />
+    </ItemGroup>
 </Project>

+ 6 - 3
Masuit.Tools.Core/Masuit.Tools.Core.csproj

@@ -1,8 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
     <PropertyGroup>
-        <TargetFrameworks>netstandard2.0;netstandard2.1;net5;net6;net7</TargetFrameworks>
-        <Description>新手友好的C#万能工具库,码数吐司库(适用于.NET Core项目),包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。
+        <TargetFrameworks>netstandard2.0;netstandard2.1;net5;net6;net7;net8</TargetFrameworks>
+        <Description>全龄段友好的C#万能工具库,码数吐司库(适用于.NET Core项目),不管你是菜鸟新手还是骨灰级玩家都能轻松上手,包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。
 官网教程:https://tools.masuit.org
 github:https://github.com/ldqk/Masuit.Tools
         </Description>
@@ -35,7 +35,7 @@ github:https://github.com/ldqk/Masuit.Tools
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
+        <PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
     </ItemGroup>
 
     <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
@@ -53,6 +53,9 @@ github:https://github.com/ldqk/Masuit.Tools
     <ItemGroup Condition=" '$(TargetFramework)' == 'net7'">
         <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.13" />
     </ItemGroup>
+    <ItemGroup Condition=" '$(TargetFramework)' == 'net8'">
+        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0" />
+    </ItemGroup>
     <ItemGroup>
       <Compile Remove="..\Masuit.Tools.Abstractions\Mapping\**" />
     </ItemGroup>

+ 1 - 1
Masuit.Tools.Excel/Masuit.Tools.Excel.csproj

@@ -39,7 +39,7 @@
     </ItemGroup>
     <ItemGroup>
         <PackageReference Include="EPPlus" Version="7.0.1" />
-        <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
+        <PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
     </ItemGroup>
     <ItemGroup>
       <ProjectReference Include="..\Masuit.Tools.Abstractions\Masuit.Tools.Abstractions.csproj" />

+ 3 - 3
Test/Masuit.Tools.Core.Test/Masuit.Tools.Core.Test.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net7.0</TargetFramework>
+    <TargetFramework>net8.0</TargetFramework>
 
     <IsPackable>false</IsPackable>
 
@@ -9,8 +9,8 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.13" />
-    <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
+    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="8.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
     <PackageReference Include="xunit" Version="2.6.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">

+ 1 - 1
Test/Masuit.Tools.Test/Masuit.Tools.Test.csproj

@@ -122,7 +122,7 @@
       <Version>2.0.3</Version>
     </PackageReference>
     <PackageReference Include="xunit.analyzers">
-      <Version>1.4.0</Version>
+      <Version>1.5.0</Version>
     </PackageReference>
     <PackageReference Include="xunit.assert">
       <Version>2.6.1</Version>