Jelajahi Sumber

精简代码

懒得勤快 1 tahun lalu
induk
melakukan
8e10f5f1bd
100 mengubah file dengan 3554 tambahan dan 3746 penghapusan
  1. 2 2
      Masuit.Tools.Abstractions/Database/DataTableBuilder.cs
  2. 41 46
      Masuit.Tools.Abstractions/DateTimeExt/ChineseCalendar.cs
  3. 13 14
      Masuit.Tools.Abstractions/Extensions/BaseType/BigIntegerExtensions.cs
  4. 42 43
      Masuit.Tools.Abstractions/Extensions/BaseType/DoubleExtensions.cs
  5. 274 275
      Masuit.Tools.Abstractions/Extensions/BaseType/IConvertibleExtensions.cs
  6. 973 974
      Masuit.Tools.Abstractions/Extensions/BaseType/IDictionaryExtensions.cs
  7. 26 27
      Masuit.Tools.Abstractions/Extensions/BaseType/IPAddressExtensions.cs
  8. 22 24
      Masuit.Tools.Abstractions/Extensions/BaseType/IntExtensions.cs
  9. 41 42
      Masuit.Tools.Abstractions/Extensions/BaseType/LongExtensions.cs
  10. 316 323
      Masuit.Tools.Abstractions/Extensions/BaseType/ObjectExtensions.cs
  11. 26 27
      Masuit.Tools.Abstractions/Extensions/BaseType/RandomExtensions.cs
  12. 11 12
      Masuit.Tools.Abstractions/Extensions/BaseType/ShortExtensions.cs
  13. 259 264
      Masuit.Tools.Abstractions/Extensions/BaseType/StreamExtensions.cs
  14. 915 919
      Masuit.Tools.Abstractions/Extensions/BaseType/StringExtensions.cs
  15. 166 167
      Masuit.Tools.Abstractions/Extensions/BaseType/ValueTypeConvertExtensions.cs
  16. 22 25
      Masuit.Tools.Abstractions/Extensions/Dynamics/Behaviors/ArrayBehavior.cs
  17. 2 9
      Masuit.Tools.Abstractions/Extensions/Dynamics/Behaviors/InterfaceProxyBehavior.cs
  18. 5 9
      Masuit.Tools.Abstractions/Extensions/Dynamics/Behaviors/NullBehavior.cs
  19. 52 57
      Masuit.Tools.Abstractions/Extensions/Dynamics/Clay.cs
  20. 1 6
      Masuit.Tools.Abstractions/Extensions/Dynamics/ClayBehaviorCollection.cs
  21. 1 6
      Masuit.Tools.Abstractions/Extensions/Dynamics/ClayMetaObject.cs
  22. 4 11
      Masuit.Tools.Abstractions/Extensions/Dynamics/DefaultClayActivator.cs
  23. 7 21
      Masuit.Tools.Abstractions/Extensions/Dynamics/Implementation/Arguments.cs
  24. 218 314
      Masuit.Tools.Abstractions/Files/FileDetector/AbstractCompoundFileDetailDetector.cs
  25. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/AbstractFullRegexDetector.cs
  26. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/AbstractISOBaseMediaFileDetailDetector.cs
  27. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/AbstractRegexSignatureDetector.cs
  28. 2 11
      Masuit.Tools.Abstractions/Files/FileDetector/AbstractZipDetailDetector.cs
  29. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ApkDetector.cs
  30. 3 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/AudioVideoInterleaveDetector.cs
  31. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/BashShellScriptDetector.cs
  32. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/BinaryPropertyListDetector.cs
  33. 3 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/BitmapDetector.cs
  34. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/Bzip2Detector.cs
  35. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CabDetector.cs
  36. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CertDetector.cs
  37. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CompoundHWPDetector.cs
  38. 3 9
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ConfigurationDetector.cs
  39. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CursorDetector.cs
  40. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DLLDetector.cs
  41. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DMGDetector.cs
  42. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DOCXDetector.cs
  43. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DirectDrawSurfaceFormatDetector.cs
  44. 3 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/EXEDetector.cs
  45. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/EpubDetector.cs
  46. 4 4
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/FLVDetector.cs
  47. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/FlacDetector.cs
  48. 3 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/GifDetector.cs
  49. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/GzDetector.cs
  50. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/HWPDetector.cs
  51. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ISODetector.cs
  52. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/IconDetector.cs
  53. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/InitializationDetector.cs
  54. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/JavaClassDetector.cs
  55. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/Jpeg2000Detector.cs
  56. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/JpegDetector.cs
  57. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/JpegXRDetector.cs
  58. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/KTXDetector.cs
  59. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/LzhDetector.cs
  60. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/M4ADetector.cs
  61. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/M4VDetector.cs
  62. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MP3Detector.cs
  63. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MP4Detector.cs
  64. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftExcelXLSDetector.cs
  65. 4 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftInstallerDetector.cs
  66. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftPowerPointPPTDetector.cs
  67. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftWordDocDetector.cs
  68. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MidiDetector.cs
  69. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MikeOBrienPackDetector.cs
  70. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OggDetector.cs
  71. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentFormulaDetector.cs
  72. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentGraphicsDetector.cs
  73. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentPresentationDetector.cs
  74. 3 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentSpreadSheetDetector.cs
  75. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentTextDetector.cs
  76. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PAKArchiveDetector.cs
  77. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PDBDetector.cs
  78. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PFXDetector.cs
  79. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PKMDetector.cs
  80. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PPSXDetector.cs
  81. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PPTXDetector.cs
  82. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PdfDetector.cs
  83. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PngDetector.cs
  84. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PrePOSIXtarDetector.cs
  85. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PsdDetector.cs
  86. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/QuakeArchiveDetector.cs
  87. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/QuickTimeDetector.cs
  88. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/REGDetector.cs
  89. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/RarDetector.cs
  90. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/RedhatPackageManagerPackageDetector.cs
  91. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/RichTextFormatDetector.cs
  92. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/SQLiteDetector.cs
  93. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/SRTDetector.cs
  94. 3 3
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ShockwaveFlashDetector.cs
  95. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/TextDetector.cs
  96. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/TgaDetector.cs
  97. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ThumbsDBDetector.cs
  98. 2 2
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/TiffDetector.cs
  99. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/UStarFormatTarDetector.cs
  100. 1 1
      Masuit.Tools.Abstractions/Files/FileDetector/Detectors/VisualStudioSolutionDetector.cs

+ 2 - 2
Masuit.Tools.Abstractions/Database/DataTableBuilder.cs

@@ -5,7 +5,7 @@ using System.Reflection.Emit;
 
 namespace Masuit.Tools.Database
 {
-    internal class DataTableBuilder<T>
+    internal sealed class DataTableBuilder<T>
     {
         private static readonly MethodInfo GetValueMethod = typeof(DataRow).GetMethod("get_Item", new[]
         {
@@ -32,7 +32,7 @@ namespace Masuit.Tools.Database
 
         public static DataTableBuilder<T> CreateBuilder(DataRow dataRecord)
         {
-            DynamicMethod methodCreateEntity = new DynamicMethod("DynamicCreateEntity", typeof(T), new[]
+            var methodCreateEntity = new DynamicMethod("DynamicCreateEntity", typeof(T), new[]
             {
                 typeof(DataRow)
             }, typeof(T), true);

+ 41 - 46
Masuit.Tools.Abstractions/DateTimeExt/ChineseCalendar.cs

@@ -12,12 +12,7 @@ namespace Masuit.Tools.DateTimeExt
     /// </remarks>
     public class ChineseCalendar
     {
-        private class ChineseCalendarException : Exception
-        {
-            public ChineseCalendarException(string msg) : base(msg)
-            {
-            }
-        }
+        private class ChineseCalendarException(string msg) : Exception(msg);
 
         private readonly DateTime _datetime;
 
@@ -161,18 +156,18 @@ namespace Masuit.Tools.DateTimeExt
         /// <summary>
         /// 自定义的工作日
         /// </summary>
-        public static HashSet<DateTime> CustomWorkDays { get; } = new HashSet<DateTime>();
+        public static HashSet<DateTime> CustomWorkDays { get; } = [];
 
         /// <summary>
         /// 自定义的节假日
         /// </summary>
-        public static Dictionary<DateTime, string> CustomHolidays { get; } = new Dictionary<DateTime, string>();
+        public static Dictionary<DateTime, string> CustomHolidays { get; } = new();
 
         /// <summary>
         /// 按公历计算的通用节假日
         /// </summary>
-        private static HashSet<DateInfoStruct> SolarHolidayInfo { get; } = new HashSet<DateInfoStruct>
-        {
+        private static HashSet<DateInfoStruct> SolarHolidayInfo { get; } =
+        [
             new DateInfoStruct(1, 1, 1, "元旦"),
             new DateInfoStruct(2, 2, 0, "世界湿地日"),
             new DateInfoStruct(2, 10, 0, "国际气象节"),
@@ -220,13 +215,13 @@ namespace Masuit.Tools.DateTimeExt
             new DateInfoStruct(12, 24, 0, "平安夜"),
             new DateInfoStruct(12, 25, 0, "圣诞节"),
             new DateInfoStruct(12, 26, 0, " 诞辰纪念")
-        };
+        ];
 
         /// <summary>
         /// 按农历计算的通用节假日
         /// </summary>
-        private static HashSet<DateInfoStruct> LunarHolidayInfo { get; } = new HashSet<DateInfoStruct>
-        {
+        private static HashSet<DateInfoStruct> LunarHolidayInfo { get; } =
+        [
             new DateInfoStruct(1, 1, 6, "春节"),
             new DateInfoStruct(1, 15, 0, "元宵节"),
             new DateInfoStruct(5, 5, 1, "端午节"),
@@ -236,21 +231,21 @@ namespace Masuit.Tools.DateTimeExt
             new DateInfoStruct(9, 9, 0, "重阳节"),
             new DateInfoStruct(12, 8, 0, "腊八节"),
             new DateInfoStruct(12, 23, 0, "北方小年(扫房)"),
-            new DateInfoStruct(12, 24, 0, "南方小年(掸尘)"),
+            new DateInfoStruct(12, 24, 0, "南方小年(掸尘)")
 
             //new HolidayStruct(12, 30, 0, "除夕")  //注意除夕需要其它方法进行计算
-        };
+        ];
 
         private static readonly WeekHolidayStruct[] WHolidayInfo =
         {
-            new WeekHolidayStruct(5, 2, 1, "母亲节"),
-            new WeekHolidayStruct(5, 3, 1, "全国助残日"),
-            new WeekHolidayStruct(6, 3, 1, "父亲节"),
-            new WeekHolidayStruct(9, 3, 3, "国际和平日"),
-            new WeekHolidayStruct(9, 4, 1, "国际聋人节"),
-            new WeekHolidayStruct(10, 1, 2, "国际住房日"),
-            new WeekHolidayStruct(10, 1, 4, "国际减轻自然灾害日"),
-            new WeekHolidayStruct(11, 4, 5, "感恩节")
+            new(5, 2, 1, "母亲节"),
+            new(5, 3, 1, "全国助残日"),
+            new(6, 3, 1, "父亲节"),
+            new(9, 3, 3, "国际和平日"),
+            new(9, 4, 1, "国际聋人节"),
+            new(10, 1, 2, "国际住房日"),
+            new(10, 1, 4, "国际减轻自然灾害日"),
+            new(11, 4, 5, "感恩节")
         };
 
         #endregion 节日数据
@@ -508,7 +503,7 @@ namespace Masuit.Tools.DateTimeExt
                 throw new ChineseCalendarException("非法农历日期");
             }
 
-            if (day < 1 || day > 30) //中国的月最多30天
+            if (day is < 1 or > 30) //中国的月最多30天
             {
                 throw new ChineseCalendarException("非法农历日期");
             }
@@ -848,22 +843,22 @@ namespace Masuit.Tools.DateTimeExt
         /// <summary>
         /// 农历今天
         /// </summary>
-        public static ChineseCalendar Today => new ChineseCalendar(DateTime.Today);
+        public static ChineseCalendar Today => new(DateTime.Today);
 
         /// <summary>
         /// 是否闰月
         /// </summary>
-        public bool IsChineseLeapMonth { get; private set; }
+        public bool IsChineseLeapMonth { get; }
 
         /// <summary>
         /// 当年是否有闰月
         /// </summary>
-        public bool IsChineseLeapYear { get; private set; }
+        public bool IsChineseLeapYear { get; }
 
         /// <summary>
         /// 农历日
         /// </summary>
-        public int ChineseDay { get; private set; }
+        public int ChineseDay { get; }
 
         /// <summary>
         /// 农历日中文表示
@@ -880,7 +875,7 @@ namespace Masuit.Tools.DateTimeExt
         /// <summary>
         /// 农历的月份
         /// </summary>
-        public int ChineseMonth { get; private set; }
+        public int ChineseMonth { get; }
 
         /// <summary>
         /// 农历月份字符串
@@ -890,7 +885,7 @@ namespace Masuit.Tools.DateTimeExt
         /// <summary>
         /// 取农历年份
         /// </summary>
-        public int ChineseYear { get; private set; }
+        public int ChineseYear { get; }
 
         /// <summary>
         /// 取农历年字符串如,一九九七年
@@ -941,7 +936,7 @@ namespace Masuit.Tools.DateTimeExt
         {
             get
             {
-                var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0); //#1/6/1900 2:05:00 AM#
+                var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0, DateTimeKind.Local); //#1/6/1900 2:05:00 AM#
                 string tempStr = "";
                 var y = Date.Year;
                 for (int i = 1; i <= 24; i++)
@@ -968,7 +963,7 @@ namespace Masuit.Tools.DateTimeExt
         {
             get
             {
-                DateTime baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0); //#1/6/1900 2:05:00 AM#
+                DateTime baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0, DateTimeKind.Local); //#1/6/1900 2:05:00 AM#
                 string tempStr = "";
                 var y = Date.Year;
                 for (int i = 24; i >= 1; i--)
@@ -993,7 +988,7 @@ namespace Masuit.Tools.DateTimeExt
         {
             get
             {
-                var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0); //#1/6/1900 2:05:00 AM#
+                var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0, DateTimeKind.Local); //#1/6/1900 2:05:00 AM#
                 string tempStr = "";
                 var y = Date.Year;
                 for (int i = 1; i <= 24; i++)
@@ -1027,31 +1022,31 @@ namespace Masuit.Tools.DateTimeExt
                 var m = Date.Month;
                 var d = Date.Day;
                 var y = m * 100 + d;
-                if (y >= 321 && y <= 419)
+                if (y is >= 321 and <= 419)
                 {
                     index = 0;
                 }
-                else if (y >= 420 && y <= 520)
+                else if (y is >= 420 and <= 520)
                 {
                     index = 1;
                 }
-                else if (y >= 521 && y <= 620)
+                else if (y is >= 521 and <= 620)
                 {
                     index = 2;
                 }
-                else if (y >= 621 && y <= 722)
+                else if (y is >= 621 and <= 722)
                 {
                     index = 3;
                 }
-                else if (y >= 723 && y <= 822)
+                else if (y is >= 723 and <= 822)
                 {
                     index = 4;
                 }
-                else if (y >= 823 && y <= 922)
+                else if (y is >= 823 and <= 922)
                 {
                     index = 5;
                 }
-                else if (y >= 923 && y <= 1022)
+                else if (y is >= 923 and <= 1022)
                 {
                     index = 6;
                 }
@@ -1059,19 +1054,19 @@ namespace Masuit.Tools.DateTimeExt
                 {
                     index = 7;
                 }
-                else if (y >= 1122 && y <= 1221)
+                else if (y is >= 1122 and <= 1221)
                 {
                     index = 8;
                 }
-                else if (y >= 1222 || y <= 119)
+                else if (y is >= 1222 or <= 119)
                 {
                     index = 9;
                 }
-                else if (y >= 120 && y <= 218)
+                else if (y is >= 120 and <= 218)
                 {
                     index = 10;
                 }
-                else if (y >= 219 && y <= 320)
+                else if (y is >= 219 and <= 320)
                 {
                     index = 11;
                 }
@@ -1198,13 +1193,13 @@ namespace Masuit.Tools.DateTimeExt
         /// 取下一天
         /// </summary>
         /// <returns></returns>
-        public ChineseCalendar NextDay => new ChineseCalendar(Date.AddDays(1));
+        public ChineseCalendar NextDay => new(Date.AddDays(1));
 
         /// <summary>
         /// 取前一天
         /// </summary>
         /// <returns></returns>
-        public ChineseCalendar PervDay => new ChineseCalendar(Date.AddDays(-1));
+        public ChineseCalendar PervDay => new(Date.AddDays(-1));
 
         /// <summary>
         /// 取下n天

+ 13 - 14
Masuit.Tools.Abstractions/Extensions/BaseType/BigIntegerExtensions.cs

@@ -1,20 +1,19 @@
 using Masuit.Tools.Strings;
 using System.Numerics;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class BigIntegerExtensions
 {
-    public static class BigIntegerExtensions
+    /// <summary>
+    /// 十进制转任意进制
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="base">进制</param>
+    /// <returns></returns>
+    public static string ToBase(this BigInteger num, byte @base)
     {
-        /// <summary>
-        /// 十进制转任意进制
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="base">进制</param>
-        /// <returns></returns>
-        public static string ToBase(this BigInteger num, byte @base)
-        {
-            var nf = new NumberFormater(@base);
-            return nf.ToString(num);
-        }
+        var nf = new NumberFormater(@base);
+        return nf.ToString(num);
     }
-}
+}

+ 42 - 43
Masuit.Tools.Abstractions/Extensions/BaseType/DoubleExtensions.cs

@@ -1,51 +1,50 @@
 using System;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class DoubleExtensions
 {
-    public static class DoubleExtensions
+    /// <summary>
+    /// 转decimal
+    /// </summary>
+    /// <param name="num"></param>
+    /// <returns></returns>
+    public static decimal ToDecimal(this double num)
     {
-        /// <summary>
-        /// 转decimal
-        /// </summary>
-        /// <param name="num"></param>
-        /// <returns></returns>
-        public static decimal ToDecimal(this double num)
-        {
-            return (decimal)num;
-        }
+        return (decimal)num;
+    }
 
-        /// <summary>
-        /// 转decimal
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="precision">小数位数</param>
-        /// <param name="mode">四舍五入策略</param>
-        /// <returns></returns>
-        public static decimal ToDecimal(this double num, int precision, MidpointRounding mode = MidpointRounding.AwayFromZero)
-        {
-            return Math.Round((decimal)num, precision, mode);
-        }
+    /// <summary>
+    /// 转decimal
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="precision">小数位数</param>
+    /// <param name="mode">四舍五入策略</param>
+    /// <returns></returns>
+    public static decimal ToDecimal(this double num, int precision, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    {
+        return Math.Round((decimal)num, precision, mode);
+    }
 
-        /// <summary>
-        /// 转decimal
-        /// </summary>
-        /// <param name="num"></param>
-        /// <returns></returns>
-        public static decimal ToDecimal(this float num)
-        {
-            return (decimal)num;
-        }
+    /// <summary>
+    /// 转decimal
+    /// </summary>
+    /// <param name="num"></param>
+    /// <returns></returns>
+    public static decimal ToDecimal(this float num)
+    {
+        return (decimal)num;
+    }
 
-        /// <summary>
-        /// 转decimal
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="precision">小数位数</param>
-        /// <param name="mode">四舍五入策略</param>
-        /// <returns></returns>
-        public static decimal ToDecimal(this float num, int precision, MidpointRounding mode = MidpointRounding.AwayFromZero)
-        {
-            return Math.Round((decimal)num, precision, mode);
-        }
+    /// <summary>
+    /// 转decimal
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="precision">小数位数</param>
+    /// <param name="mode">四舍五入策略</param>
+    /// <returns></returns>
+    public static decimal ToDecimal(this float num, int precision, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    {
+        return Math.Round((decimal)num, precision, mode);
     }
-}
+}

+ 274 - 275
Masuit.Tools.Abstractions/Extensions/BaseType/IConvertibleExtensions.cs

@@ -1,284 +1,283 @@
 using System;
 using System.ComponentModel;
 using System.Globalization;
-using System.Linq;
 
 namespace Masuit.Tools;
 
 public static class IConvertibleExtensions
 {
-	public static bool IsNumeric(this Type type)
-	{
-		switch (Type.GetTypeCode(type))
-		{
-			case TypeCode.Byte:
-			case TypeCode.SByte:
-			case TypeCode.UInt16:
-			case TypeCode.UInt32:
-			case TypeCode.UInt64:
-			case TypeCode.Int16:
-			case TypeCode.Int32:
-			case TypeCode.Int64:
-			case TypeCode.Decimal:
-			case TypeCode.Double:
-			case TypeCode.Single:
-				return true;
-
-			default:
-				return false;
-		}
-	}
-
-	/// <summary>
-	/// 类型直转
-	/// </summary>
-	/// <typeparam name="T"></typeparam>
-	/// <param name="value"></param>
-	/// <returns></returns>
-
-	public static T ConvertTo<T>(this IConvertible value) where T : IConvertible
-	{
-		if (value != null)
-		{
-			var type = typeof(T);
-			if (value.GetType() == type)
-			{
-				return (T)value;
-			}
-
-			if (type.IsNumeric())
-			{
-				return (T)value.ToType(type, new NumberFormatInfo());
-			}
-
-			if (value == DBNull.Value)
-			{
-				return default;
-			}
-
-			if (type.IsEnum)
-			{
-				return (T)Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
-			}
-
-			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
-			{
-				var underlyingType = Nullable.GetUnderlyingType(type);
-				return (T)(underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType));
-			}
-
-			var converter = TypeDescriptor.GetConverter(value);
-			if (converter.CanConvertTo(type))
-			{
-				return (T)converter.ConvertTo(value, type);
-			}
-
-			converter = TypeDescriptor.GetConverter(type);
-			if (converter.CanConvertFrom(value.GetType()))
-			{
-				return (T)converter.ConvertFrom(value);
-			}
-
-			return (T)Convert.ChangeType(value, type);
-		}
-
-		return (T)value;
-	}
-
-	/// <summary>
-	/// 类型直转
-	/// </summary>
-	/// <typeparam name="T"></typeparam>
-	/// <param name="value"></param>
-	/// <param name="defaultValue">转换失败的默认值</param>
-	/// <returns></returns>
-	public static T TryConvertTo<T>(this IConvertible value, T defaultValue = default) where T : IConvertible
-	{
-		try
-		{
-			return ConvertTo<T>(value);
-		}
-		catch
-		{
-			return defaultValue;
-		}
-	}
-
-	/// <summary>
-	/// 类型直转
-	/// </summary>
-	/// <typeparam name="T"></typeparam>
-	/// <param name="value"></param>
-	/// <param name="result">转换失败的默认值</param>
-	/// <returns></returns>
-	public static bool TryConvertTo<T>(this IConvertible value, out T result) where T : IConvertible
-	{
-		try
-		{
-			result = ConvertTo<T>(value);
-			return true;
-		}
-		catch
-		{
-			result = default;
-			return false;
-		}
-	}
-
-	/// <summary>
-	/// 类型直转
-	/// </summary>
-	/// <param name="value"></param>
-	/// <param name="type">目标类型</param>
-	/// <param name="result">转换失败的默认值</param>
-	/// <returns></returns>
-	public static bool TryConvertTo(this IConvertible value, Type type, out object result)
-	{
-		try
-		{
-			result = ConvertTo(value, type);
-			return true;
-		}
-		catch
-		{
-			result = default;
-			return false;
-		}
-	}
-
-	/// <summary>
-	/// 类型直转
-	/// </summary>
-	/// <param name="value"></param>
-	/// <param name="type">目标类型</param>
-	/// <returns></returns>
-	public static object ConvertTo(this IConvertible value, Type type)
-	{
-		if (value == null)
-		{
-			return default;
-		}
-
-		if (value.GetType() == type)
-		{
-			return value;
-		}
-
-		if (value == DBNull.Value)
-		{
-			return null;
-		}
-
-		if (type.IsAssignableFrom(typeof(string)))
-		{
-			return value.ToString();
-		}
-
-		if (type.IsEnum)
-		{
-			return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
-		}
-
-		if (type.IsAssignableFrom(typeof(Guid)))
-		{
-			return Guid.Parse(value.ToString());
-		}
-
-		if (type.IsAssignableFrom(typeof(DateTime)))
-		{
-			return DateTime.Parse(value.ToString());
-		}
-
-		if (type.IsAssignableFrom(typeof(DateTimeOffset)))
-		{
-			return DateTimeOffset.Parse(value.ToString());
-		}
-
-		if (type.IsNumeric())
-		{
-			return value.ToType(type, new NumberFormatInfo());
-		}
-
-		if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
-		{
-			var underlyingType = Nullable.GetUnderlyingType(type);
-			return underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType);
-		}
-
-		var converter = TypeDescriptor.GetConverter(value);
-		if (converter.CanConvertTo(type))
-		{
-			return converter.ConvertTo(value, type);
-		}
-
-		converter = TypeDescriptor.GetConverter(type);
-		return converter.CanConvertFrom(value.GetType()) ? converter.ConvertFrom(value) : Convert.ChangeType(value, type);
-	}
-
-	/// <summary>
-	/// 对象类型转换
-	/// </summary>
-	/// <param name="this">当前值</param>
-	/// <returns>转换后的对象</returns>
-	public static T ChangeTypeTo<T>(this object @this)
-	{
-		return (T)ChangeType(@this, typeof(T));
-	}
-
-	/// <summary>
-	/// 对象类型转换
-	/// </summary>
-	/// <param name="this">当前值</param>
-	/// <param name="type">指定类型的类型</param>
-	/// <returns>转换后的对象</returns>
-	public static object ChangeType(this object @this, Type type)
-	{
-		var currType = Nullable.GetUnderlyingType(@this.GetType()) ?? @this.GetType();
-		type = Nullable.GetUnderlyingType(type) ?? type;
-		if (@this == DBNull.Value)
-		{
-			if (!type.IsValueType)
-			{
-				return null;
-			}
-
-			throw new Exception("不能将null值转换为" + type.Name + "类型!");
-		}
-
-		if (currType == type)
-		{
-			return @this;
-		}
-
-		if (type.IsAssignableFrom(typeof(string)))
-		{
-			return @this.ToString();
-		}
-
-		if (type.IsEnum)
-		{
-			return Enum.Parse(type, @this.ToString(), true);
-		}
-
-		if (type.IsAssignableFrom(typeof(Guid)))
-		{
-			return Guid.Parse(@this.ToString());
-		}
-
-		if (!type.IsArray || !currType.IsArray)
-		{
-			return Convert.ChangeType(@this, type);
-		}
-
-		var length = ((Array)@this).Length;
-		var targetType = Type.GetType(type.FullName.Trim('[', ']'));
-		var array = Array.CreateInstance(targetType, length);
-		for (int j = 0; j < length; j++)
-		{
-			var tmp = ((Array)@this).GetValue(j);
-			array.SetValue(ChangeType(tmp, targetType), j);
-		}
-
-		return array;
-	}
+    public static bool IsNumeric(this Type type)
+    {
+        switch (Type.GetTypeCode(type))
+        {
+            case TypeCode.Byte:
+            case TypeCode.SByte:
+            case TypeCode.UInt16:
+            case TypeCode.UInt32:
+            case TypeCode.UInt64:
+            case TypeCode.Int16:
+            case TypeCode.Int32:
+            case TypeCode.Int64:
+            case TypeCode.Decimal:
+            case TypeCode.Double:
+            case TypeCode.Single:
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+    /// <summary>
+    /// 类型直转
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="value"></param>
+    /// <returns></returns>
+
+    public static T ConvertTo<T>(this IConvertible value) where T : IConvertible
+    {
+        if (value != null)
+        {
+            var type = typeof(T);
+            if (value.GetType() == type)
+            {
+                return (T)value;
+            }
+
+            if (type.IsNumeric())
+            {
+                return (T)value.ToType(type, new NumberFormatInfo());
+            }
+
+            if (value == DBNull.Value)
+            {
+                return default;
+            }
+
+            if (type.IsEnum)
+            {
+                return (T)Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
+            }
+
+            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
+            {
+                var underlyingType = Nullable.GetUnderlyingType(type);
+                return (T)(underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType));
+            }
+
+            var converter = TypeDescriptor.GetConverter(value);
+            if (converter.CanConvertTo(type))
+            {
+                return (T)converter.ConvertTo(value, type);
+            }
+
+            converter = TypeDescriptor.GetConverter(type);
+            if (converter.CanConvertFrom(value.GetType()))
+            {
+                return (T)converter.ConvertFrom(value);
+            }
+
+            return (T)Convert.ChangeType(value, type);
+        }
+
+        return (T)value;
+    }
+
+    /// <summary>
+    /// 类型直转
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="value"></param>
+    /// <param name="defaultValue">转换失败的默认值</param>
+    /// <returns></returns>
+    public static T TryConvertTo<T>(this IConvertible value, T defaultValue = default) where T : IConvertible
+    {
+        try
+        {
+            return ConvertTo<T>(value);
+        }
+        catch
+        {
+            return defaultValue;
+        }
+    }
+
+    /// <summary>
+    /// 类型直转
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="value"></param>
+    /// <param name="result">转换失败的默认值</param>
+    /// <returns></returns>
+    public static bool TryConvertTo<T>(this IConvertible value, out T result) where T : IConvertible
+    {
+        try
+        {
+            result = ConvertTo<T>(value);
+            return true;
+        }
+        catch
+        {
+            result = default;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 类型直转
+    /// </summary>
+    /// <param name="value"></param>
+    /// <param name="type">目标类型</param>
+    /// <param name="result">转换失败的默认值</param>
+    /// <returns></returns>
+    public static bool TryConvertTo(this IConvertible value, Type type, out object result)
+    {
+        try
+        {
+            result = ConvertTo(value, type);
+            return true;
+        }
+        catch
+        {
+            result = default;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 类型直转
+    /// </summary>
+    /// <param name="value"></param>
+    /// <param name="type">目标类型</param>
+    /// <returns></returns>
+    public static object ConvertTo(this IConvertible value, Type type)
+    {
+        if (value == null)
+        {
+            return default;
+        }
+
+        if (value.GetType() == type)
+        {
+            return value;
+        }
+
+        if (value == DBNull.Value)
+        {
+            return null;
+        }
+
+        if (type.IsAssignableFrom(typeof(string)))
+        {
+            return value.ToString();
+        }
+
+        if (type.IsEnum)
+        {
+            return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
+        }
+
+        if (type.IsAssignableFrom(typeof(Guid)))
+        {
+            return Guid.Parse(value.ToString());
+        }
+
+        if (type.IsAssignableFrom(typeof(DateTime)))
+        {
+            return DateTime.Parse(value.ToString());
+        }
+
+        if (type.IsAssignableFrom(typeof(DateTimeOffset)))
+        {
+            return DateTimeOffset.Parse(value.ToString());
+        }
+
+        if (type.IsNumeric())
+        {
+            return value.ToType(type, new NumberFormatInfo());
+        }
+
+        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
+        {
+            var underlyingType = Nullable.GetUnderlyingType(type);
+            return underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType);
+        }
+
+        var converter = TypeDescriptor.GetConverter(value);
+        if (converter.CanConvertTo(type))
+        {
+            return converter.ConvertTo(value, type);
+        }
+
+        converter = TypeDescriptor.GetConverter(type);
+        return converter.CanConvertFrom(value.GetType()) ? converter.ConvertFrom(value) : Convert.ChangeType(value, type);
+    }
+
+    /// <summary>
+    /// 对象类型转换
+    /// </summary>
+    /// <param name="this">当前值</param>
+    /// <returns>转换后的对象</returns>
+    public static T ChangeTypeTo<T>(this object @this)
+    {
+        return (T)ChangeType(@this, typeof(T));
+    }
+
+    /// <summary>
+    /// 对象类型转换
+    /// </summary>
+    /// <param name="this">当前值</param>
+    /// <param name="type">指定类型的类型</param>
+    /// <returns>转换后的对象</returns>
+    public static object ChangeType(this object @this, Type type)
+    {
+        var currType = Nullable.GetUnderlyingType(@this.GetType()) ?? @this.GetType();
+        type = Nullable.GetUnderlyingType(type) ?? type;
+        if (@this == DBNull.Value)
+        {
+            if (!type.IsValueType)
+            {
+                return null;
+            }
+
+            throw new Exception("不能将null值转换为" + type.Name + "类型!");
+        }
+
+        if (currType == type)
+        {
+            return @this;
+        }
+
+        if (type.IsAssignableFrom(typeof(string)))
+        {
+            return @this.ToString();
+        }
+
+        if (type.IsEnum)
+        {
+            return Enum.Parse(type, @this.ToString(), true);
+        }
+
+        if (type.IsAssignableFrom(typeof(Guid)))
+        {
+            return Guid.Parse(@this.ToString());
+        }
+
+        if (!type.IsArray || !currType.IsArray)
+        {
+            return Convert.ChangeType(@this, type);
+        }
+
+        var length = ((Array)@this).Length;
+        var targetType = Type.GetType(type.FullName.Trim('[', ']'));
+        var array = Array.CreateInstance(targetType, length);
+        for (int j = 0; j < length; j++)
+        {
+            var tmp = ((Array)@this).GetValue(j);
+            array.SetValue(ChangeType(tmp, targetType), j);
+        }
+
+        return array;
+    }
 }

+ 973 - 974
Masuit.Tools.Abstractions/Extensions/BaseType/IDictionaryExtensions.cs

@@ -5,1152 +5,1151 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class IDictionaryExtensions
 {
-    public static class IDictionaryExtensions
-    {
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    {
+        foreach (var item in that)
         {
-            foreach (var item in that)
-            {
-                @this[item.Key] = item.Value;
-            }
+            @this[item.Key] = item.Value;
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        public static void AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    public static void AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    {
+        foreach (var item in that)
         {
-            foreach (var item in that)
-            {
-                @this[item.Key] = item.Value;
-            }
+            @this[item.Key] = item.Value;
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        public static void AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    public static void AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    {
+        foreach (var item in that)
         {
-            foreach (var item in that)
-            {
-                @this[item.Key] = item.Value;
-            }
+            @this[item.Key] = item.Value;
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    {
+        foreach (var item in @this)
         {
-            foreach (var item in @this)
-            {
-                that[item.Key] = item.Value;
-            }
+            that[item.Key] = item.Value;
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        public static void AddOrUpdateTo<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    public static void AddOrUpdateTo<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    {
+        foreach (var item in @this)
         {
-            foreach (var item in @this)
-            {
-                that[item.Key] = item.Value;
-            }
+            that[item.Key] = item.Value;
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        public static void AddOrUpdateTo<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    public static void AddOrUpdateTo<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
+    {
+        foreach (var item in @this)
         {
-            foreach (var item in @this)
-            {
-                that[item.Key] = item.Value;
-            }
+            that[item.Key] = item.Value;
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        if ([email protected](key, addValue))
         {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = updateValueFactory(key, @this[key]);
-            }
-
-            return @this[key];
+            @this[key] = updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
-        {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = updateValueFactory(key, @this[key]);
-            }
-
-            return @this[key];
-        }
+        return @this[key];
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        if ([email protected](key, addValue))
         {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = updateValueFactory(key, @this[key]);
-            }
-
-            return @this[key];
+            @this[key] = updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
-        {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = await updateValueFactory(key, @this[key]);
-            }
-
-            return @this[key];
-        }
+        return @this[key];
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        if ([email protected](key, addValue))
         {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = await updateValueFactory(key, @this[key]);
-            }
-
-            return @this[key];
+            @this[key] = updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
-        {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = await updateValueFactory(key, @this[key]);
-            }
-
-            return @this[key];
-        }
+        return @this[key];
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValue">更新时的值</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        if ([email protected](key, addValue))
         {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = updateValue;
-            }
-
-            return @this[key];
+            @this[key] = await updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValue">更新时的值</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
-        {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = updateValue;
-            }
-
-            return @this[key];
-        }
+        return @this[key];
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValue">添加时的值</param>
-        /// <param name="updateValue">更新时的值</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        if ([email protected](key, addValue))
         {
-            if ([email protected](key, addValue))
-            {
-                @this[key] = updateValue;
-            }
-
-            return @this[key];
+            @this[key] = await updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
-        {
-            foreach (var item in that)
-            {
-                AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
-            }
-        }
+        return @this[key];
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static void AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        if ([email protected](key, addValue))
         {
-            foreach (var item in that)
-            {
-                AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
-            }
+            @this[key] = await updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static void AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
-        {
-            foreach (var item in that)
-            {
-                AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
-            }
-        }
+        return @this[key];
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static Task AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValue">更新时的值</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
+    {
+        if ([email protected](key, addValue))
         {
-            return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
+            @this[key] = updateValue;
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static Task AddOrUpdateAsync<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+        return @this[key];
+    }
+
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValue">更新时的值</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
+    {
+        if ([email protected](key, addValue))
         {
-            return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
+            @this[key] = updateValue;
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static Task AddOrUpdateAsync<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+        return @this[key];
+    }
+
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValue">添加时的值</param>
+    /// <param name="updateValue">更新时的值</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
+    {
+        if ([email protected](key, addValue))
         {
-            return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
+            @this[key] = updateValue;
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+        return @this[key];
+    }
+
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        foreach (var item in that)
         {
-            foreach (var item in @this)
-            {
-                AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
-            }
+            AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static void AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        foreach (var item in that)
         {
-            foreach (var item in @this)
-            {
-                AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
-            }
+            AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableConcurrentDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static void AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        foreach (var item in that)
         {
-            foreach (var item in @this)
-            {
-                AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
-            }
+            AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
         }
+    }
+
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static Task AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
+    }
+
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static Task AddOrUpdateAsync<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
+    }
+
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static Task AddOrUpdateAsync<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        foreach (var item in @this)
         {
-            return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
+            AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        foreach (var item in @this)
         {
-            return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
+            AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="that">另一个字典集</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableConcurrentDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableConcurrentDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        foreach (var item in @this)
         {
-            return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
+            AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
         }
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValueFactory">添加时的操作</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
-        {
-            if ([email protected](key, addValueFactory(key)))
-            {
-                @this[key] = updateValueFactory(key, @this[key]);
-            }
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
+    }
 
-            return @this[key];
-        }
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
+    }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValueFactory">添加时的操作</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
-        {
-            if ([email protected](key, addValueFactory(key)))
-            {
-                @this[key] = updateValueFactory(key, @this[key]);
-            }
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="that">另一个字典集</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, NullableConcurrentDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValueFactory">添加时的操作</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        if ([email protected](key, addValueFactory(key)))
+        {
+            @this[key] = updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValueFactory">添加时的操作</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static TValue AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
-        {
-            if ([email protected](key, addValueFactory(key)))
-            {
-                @this[key] = updateValueFactory(key, @this[key]);
-            }
+        return @this[key];
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValueFactory">添加时的操作</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        if ([email protected](key, addValueFactory(key)))
+        {
+            @this[key] = updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValueFactory">添加时的操作</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
-        {
-            if ([email protected](key, await addValueFactory(key)))
-            {
-                @this[key] = await updateValueFactory(key, @this[key]);
-            }
+        return @this[key];
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValueFactory">添加时的操作</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static TValue AddOrUpdate<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
+    {
+        if ([email protected](key, addValueFactory(key)))
+        {
+            @this[key] = updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValueFactory">添加时的操作</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
-        {
-            if ([email protected](key, await addValueFactory(key)))
-            {
-                @this[key] = await updateValueFactory(key, @this[key]);
-            }
+        return @this[key];
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValueFactory">添加时的操作</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        if ([email protected](key, await addValueFactory(key)))
+        {
+            @this[key] = await updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 添加或更新键值对
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key">键</param>
-        /// <param name="addValueFactory">添加时的操作</param>
-        /// <param name="updateValueFactory">更新时的操作</param>
-        public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
-        {
-            if ([email protected](key, await addValueFactory(key)))
-            {
-                @this[key] = await updateValueFactory(key, @this[key]);
-            }
+        return @this[key];
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValueFactory">添加时的操作</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        if ([email protected](key, await addValueFactory(key)))
+        {
+            @this[key] = await updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 获取或添加
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key"></param>
-        /// <param name="addValueFactory"></param>
-        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TValue> addValueFactory)
-        {
-            if ([email protected](key))
-            {
-                @this[key] = addValueFactory();
-            }
+        return @this[key];
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 添加或更新键值对
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key">键</param>
+    /// <param name="addValueFactory">添加时的操作</param>
+    /// <param name="updateValueFactory">更新时的操作</param>
+    public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this NullableConcurrentDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
+    {
+        if ([email protected](key, await addValueFactory(key)))
+        {
+            @this[key] = await updateValueFactory(key, @this[key]);
         }
 
-        /// <summary>
-        /// 获取或添加
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key"></param>
-        /// <param name="addValueFactory"></param>
-        public static async Task<TValue> GetOrAddAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<Task<TValue>> addValueFactory)
-        {
-            if ([email protected](key))
-            {
-                @this[key] = await addValueFactory();
-            }
+        return @this[key];
+    }
 
-            return @this[key];
+    /// <summary>
+    /// 获取或添加
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key"></param>
+    /// <param name="addValueFactory"></param>
+    public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TValue> addValueFactory)
+    {
+        if ([email protected](key))
+        {
+            @this[key] = addValueFactory();
         }
 
-        /// <summary>
-        /// 获取或添加
-        /// </summary>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TValue"></typeparam>
-        /// <param name="this"></param>
-        /// <param name="key"></param>
-        /// <param name="addValue"></param>
-        public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> @this, TKey key, TValue addValue)
+        return @this[key];
+    }
+
+    /// <summary>
+    /// 获取或添加
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key"></param>
+    /// <param name="addValueFactory"></param>
+    public static async Task<TValue> GetOrAddAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<Task<TValue>> addValueFactory)
+    {
+        if ([email protected](key))
         {
-            return @this.TryAdd(key, addValue) ? addValue : @this[key];
+            @this[key] = await addValueFactory();
         }
 
+        return @this[key];
+    }
+
+    /// <summary>
+    /// 获取或添加
+    /// </summary>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TValue"></typeparam>
+    /// <param name="this"></param>
+    /// <param name="key"></param>
+    /// <param name="addValue"></param>
+    public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> @this, TKey key, TValue addValue)
+    {
+        return @this.TryAdd(key, addValue) ? addValue : @this[key];
+    }
+
 #if NETSTANDARD2_1_OR_GREATER
 #else
 
-        public static bool TryAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value) where TKey : notnull
-        {
-            if (dictionary == null)
-                throw new ArgumentNullException(nameof(dictionary));
-            if (dictionary.IsReadOnly||dictionary.ContainsKey(key))
-                return false;
-            dictionary.Add(key, value);
-            return true;
-        }
+    public static bool TryAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value) where TKey : notnull
+    {
+        if (dictionary == null)
+            throw new ArgumentNullException(nameof(dictionary));
+        if (dictionary.IsReadOnly || dictionary.ContainsKey(key))
+            return false;
+        dictionary.Add(key, value);
+        return true;
+    }
 
 #endif
 
-        /// <summary>
-        /// 遍历IEnumerable
-        /// </summary>
-        /// <param name="dic"></param>
-        /// <param name="action">回调方法</param>
-        public static void ForEach<TKey, TValue>(this IDictionary<TKey, TValue> dic, Action<TKey, TValue> action)
+    /// <summary>
+    /// 遍历IEnumerable
+    /// </summary>
+    /// <param name="dic"></param>
+    /// <param name="action">回调方法</param>
+    public static void ForEach<TKey, TValue>(this IDictionary<TKey, TValue> dic, Action<TKey, TValue> action)
+    {
+        foreach (var item in dic)
         {
-            foreach (var item in dic)
-            {
-                action(item.Key, item.Value);
-            }
+            action(item.Key, item.Value);
         }
+    }
 
-        /// <summary>
-        /// 遍历IDictionary
-        /// </summary>
-        /// <param name="dic"></param>
-        /// <param name="action">回调方法</param>
-        public static Task ForEachAsync<TKey, TValue>(this IDictionary<TKey, TValue> dic, Func<TKey, TValue, Task> action)
-        {
-            return dic.ForeachAsync(x => action(x.Key, x.Value));
-        }
+    /// <summary>
+    /// 遍历IDictionary
+    /// </summary>
+    /// <param name="dic"></param>
+    /// <param name="action">回调方法</param>
+    public static Task ForEachAsync<TKey, TValue>(this IDictionary<TKey, TValue> dic, Func<TKey, TValue, Task> action)
+    {
+        return dic.ForeachAsync(x => action(x.Key, x.Value));
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        public static NullableDictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    public static NullableDictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new NullableDictionary<TKey, TSource>(items.Count);
+        foreach (var item in items)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new NullableDictionary<TKey, TSource>(items.Count);
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = item;
-            }
-
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static NullableDictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue)
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static NullableDictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue)
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new NullableDictionary<TKey, TSource>(items.Count)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new NullableDictionary<TKey, TSource>(items.Count)
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = item;
-            }
-
-            return dic;
+            FallbackValue = defaultValue
+        };
+        foreach (var item in items)
+        {
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static NullableDictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static NullableDictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new NullableDictionary<TKey, TElement>(items.Count);
+        foreach (var item in items)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new NullableDictionary<TKey, TElement>(items.Count);
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
-
-            return dic;
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static NullableDictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue)
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static NullableDictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue)
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new NullableDictionary<TKey, TElement>(items.Count)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new NullableDictionary<TKey, TElement>(items.Count)
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
-
-            return dic;
+            FallbackValue = defaultValue
+        };
+        foreach (var item in items)
+        {
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static async Task<NullableDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static async Task<NullableDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new NullableDictionary<TKey, TElement>(items.Count);
+        await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static async Task<NullableDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue)
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new NullableDictionary<TKey, TElement>(items.Count)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new NullableDictionary<TKey, TElement>(items.Count);
-            await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
-        }
+            FallbackValue = defaultValue
+        };
+        await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static async Task<NullableDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue)
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    public static DisposableDictionary<TKey, TSource> ToDisposableDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) where TSource : IDisposable
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new DisposableDictionary<TKey, TSource>(items.Count);
+        foreach (var item in items)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new NullableDictionary<TKey, TElement>(items.Count)
-            {
-                FallbackValue = defaultValue
-            };
-            await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        public static DisposableDictionary<TKey, TSource> ToDisposableDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) where TSource : IDisposable
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static DisposableDictionary<TKey, TSource> ToDisposableDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue) where TSource : IDisposable
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new DisposableDictionary<TKey, TSource>(items.Count)
+        {
+            FallbackValue = defaultValue
+        };
+        foreach (var item in items)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new DisposableDictionary<TKey, TSource>(items.Count);
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = item;
-            }
-
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static DisposableDictionary<TKey, TSource> ToDisposableDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue) where TSource : IDisposable
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static DisposableDictionary<TKey, TElement> ToDisposableDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) where TElement : IDisposable
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new DisposableDictionary<TKey, TElement>(items.Count);
+        foreach (var item in items)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new DisposableDictionary<TKey, TSource>(items.Count)
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = item;
-            }
-
-            return dic;
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static DisposableDictionary<TKey, TElement> ToDisposableDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) where TElement : IDisposable
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static DisposableDictionary<TKey, TElement> ToDisposableDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue) where TElement : IDisposable
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new DisposableDictionary<TKey, TElement>(items.Count)
+        {
+            FallbackValue = defaultValue
+        };
+        foreach (var item in items)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new DisposableDictionary<TKey, TElement>(items.Count);
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
-
-            return dic;
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static DisposableDictionary<TKey, TElement> ToDisposableDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue) where TElement : IDisposable
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static async Task<DisposableDictionary<TKey, TElement>> ToDisposableDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector) where TElement : IDisposable
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new DisposableDictionary<TKey, TElement>(items.Count);
+        await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static async Task<DisposableDictionary<TKey, TElement>> ToDisposableDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue) where TElement : IDisposable
+    {
+        var items = source as IList<TSource> ?? source.ToList();
+        var dic = new DisposableDictionary<TKey, TElement>(items.Count)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new DisposableDictionary<TKey, TElement>(items.Count)
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in items)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
-
-            return dic;
-        }
+            FallbackValue = defaultValue
+        };
+        await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static async Task<DisposableDictionary<TKey, TElement>> ToDisposableDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector) where TElement : IDisposable
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    public static NullableConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+    {
+        var dic = new NullableConcurrentDictionary<TKey, TSource>();
+        foreach (var item in source)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new DisposableDictionary<TKey, TElement>(items.Count);
-            await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static async Task<DisposableDictionary<TKey, TElement>> ToDisposableDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue) where TElement : IDisposable
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static NullableConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue)
+    {
+        var dic = new NullableConcurrentDictionary<TKey, TSource>()
+        {
+            FallbackValue = defaultValue
+        };
+        foreach (var item in source)
         {
-            var items = source as IList<TSource> ?? source.ToList();
-            var dic = new DisposableDictionary<TKey, TElement>(items.Count)
-            {
-                FallbackValue = defaultValue
-            };
-            await items.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        public static NullableConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            var dic = new NullableConcurrentDictionary<TKey, TSource>();
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = item;
-            }
+        return dic;
+    }
 
-            return dic;
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static NullableConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+    {
+        var dic = new NullableConcurrentDictionary<TKey, TElement>();
+        foreach (var item in source)
+        {
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static NullableConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue)
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue"></param>
+    public static NullableConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue)
+    {
+        var dic = new NullableConcurrentDictionary<TKey, TElement>()
         {
-            var dic = new NullableConcurrentDictionary<TKey, TSource>()
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = item;
-            }
-
-            return dic;
+            FallbackValue = defaultValue
+        };
+        foreach (var item in source)
+        {
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static NullableConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
-        {
-            var dic = new NullableConcurrentDictionary<TKey, TElement>();
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
+        return dic;
+    }
 
-            return dic;
-        }
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static async Task<NullableConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
+    {
+        var dic = new ConcurrentDictionary<TKey, TElement>();
+        await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue"></param>
-        public static NullableConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue)
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <typeparam name="TElement"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static async Task<NullableConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue)
+    {
+        var dic = new NullableConcurrentDictionary<TKey, TElement>
         {
-            var dic = new NullableConcurrentDictionary<TKey, TElement>()
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
-
-            return dic;
-        }
+            FallbackValue = defaultValue
+        };
+        await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static async Task<NullableConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <typeparam name="TSource"></typeparam>
+    /// <typeparam name="TKey"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    public static DisposableConcurrentDictionary<TKey, TSource> ToDisposableConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) where TSource : IDisposable
+    {
+        var dic = new DisposableConcurrentDictionary<TKey, TSource>();
+        foreach (var item in source)
         {
-            var dic = new ConcurrentDictionary<TKey, TElement>();
-            await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <typeparam name="TElement"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static async Task<NullableConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue)
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static DisposableConcurrentDictionary<TKey, TSource> ToDisposableConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue) where TSource : IDisposable
+    {
+        var dic = new DisposableConcurrentDictionary<TKey, TSource>
+        {
+            FallbackValue = defaultValue
+        };
+        foreach (var item in source)
         {
-            var dic = new NullableConcurrentDictionary<TKey, TElement>
-            {
-                FallbackValue = defaultValue
-            };
-            await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
+            dic[keySelector(item)] = item;
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <typeparam name="TSource"></typeparam>
-        /// <typeparam name="TKey"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        public static DisposableConcurrentDictionary<TKey, TSource> ToDisposableConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) where TSource : IDisposable
-        {
-            var dic = new DisposableConcurrentDictionary<TKey, TSource>();
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = item;
-            }
+        return dic;
+    }
 
-            return dic;
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static DisposableConcurrentDictionary<TKey, TElement> ToDisposableConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) where TElement : IDisposable
+    {
+        var dic = new DisposableConcurrentDictionary<TKey, TElement>();
+        foreach (var item in source)
+        {
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static DisposableConcurrentDictionary<TKey, TSource> ToDisposableConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, TSource defaultValue) where TSource : IDisposable
+        return dic;
+    }
+
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue"></param>
+    public static DisposableConcurrentDictionary<TKey, TElement> ToDisposableConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue) where TElement : IDisposable
+    {
+        var dic = new DisposableConcurrentDictionary<TKey, TElement>()
         {
-            var dic = new DisposableConcurrentDictionary<TKey, TSource>
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = item;
-            }
-
-            return dic;
+            FallbackValue = defaultValue
+        };
+        foreach (var item in source)
+        {
+            dic[keySelector(item)] = elementSelector(item);
         }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static DisposableConcurrentDictionary<TKey, TElement> ToDisposableConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) where TElement : IDisposable
-        {
-            var dic = new DisposableConcurrentDictionary<TKey, TElement>();
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
+        return dic;
+    }
 
-            return dic;
-        }
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    public static async Task<DisposableConcurrentDictionary<TKey, TElement>> ToDisposableConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector) where TElement : IDisposable
+    {
+        var dic = new DisposableConcurrentDictionary<TKey, TElement>();
+        await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue"></param>
-        public static DisposableConcurrentDictionary<TKey, TElement> ToDisposableConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, TElement defaultValue) where TElement : IDisposable
+    /// <summary>
+    /// 安全的转换成字典集
+    /// </summary>
+    /// <param name="source"></param>
+    /// <param name="keySelector">键选择器</param>
+    /// <param name="elementSelector">值选择器</param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static async Task<DisposableConcurrentDictionary<TKey, TElement>> ToDisposableConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue) where TElement : IDisposable
+    {
+        var dic = new DisposableConcurrentDictionary<TKey, TElement>()
         {
-            var dic = new DisposableConcurrentDictionary<TKey, TElement>()
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var item in source)
-            {
-                dic[keySelector(item)] = elementSelector(item);
-            }
-
-            return dic;
-        }
+            FallbackValue = defaultValue
+        };
+        await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
+        return dic;
+    }
 
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        public static async Task<DisposableConcurrentDictionary<TKey, TElement>> ToDisposableConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector) where TElement : IDisposable
+    /// <summary>
+    /// 转换成并发字典集合
+    /// </summary>
+    public static NullableConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic) => dic;
+
+    /// <summary>
+    /// 转换成并发字典集合
+    /// </summary>
+    /// <param name="dic"></param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static NullableConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic, TValue defaultValue)
+    {
+        var nullableDictionary = new NullableConcurrentDictionary<TKey, TValue>()
         {
-            var dic = new DisposableConcurrentDictionary<TKey, TElement>();
-            await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
-        }
-
-        /// <summary>
-        /// 安全的转换成字典集
-        /// </summary>
-        /// <param name="source"></param>
-        /// <param name="keySelector">键选择器</param>
-        /// <param name="elementSelector">值选择器</param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static async Task<DisposableConcurrentDictionary<TKey, TElement>> ToDisposableConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector, TElement defaultValue) where TElement : IDisposable
+            FallbackValue = defaultValue
+        };
+        foreach (var p in dic)
         {
-            var dic = new DisposableConcurrentDictionary<TKey, TElement>()
-            {
-                FallbackValue = defaultValue
-            };
-            await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
-            return dic;
+            nullableDictionary[p.Key] = p.Value;
         }
 
-        /// <summary>
-        /// 转换成并发字典集合
-        /// </summary>
-        public static NullableConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic) => dic;
-
-        /// <summary>
-        /// 转换成并发字典集合
-        /// </summary>
-        /// <param name="dic"></param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static NullableConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic, TValue defaultValue)
-        {
-            var nullableDictionary = new NullableConcurrentDictionary<TKey, TValue>()
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var p in dic)
-            {
-                nullableDictionary[p.Key] = p.Value;
-            }
-
-            return nullableDictionary;
-        }
+        return nullableDictionary;
+    }
 
-        /// <summary>
-        /// 转换成普通字典集合
-        /// </summary>
-        public static NullableDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic) => dic;
-
-        /// <summary>
-        /// 转换成普通字典集合
-        /// </summary>
-        /// <param name="dic"></param>
-        /// <param name="defaultValue">键未找到时的默认值</param>
-        public static NullableDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic, TValue defaultValue)
+    /// <summary>
+    /// 转换成普通字典集合
+    /// </summary>
+    public static NullableDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic) => dic;
+
+    /// <summary>
+    /// 转换成普通字典集合
+    /// </summary>
+    /// <param name="dic"></param>
+    /// <param name="defaultValue">键未找到时的默认值</param>
+    public static NullableDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic, TValue defaultValue)
+    {
+        var nullableDictionary = new NullableDictionary<TKey, TValue>()
+        {
+            FallbackValue = defaultValue
+        };
+        foreach (var p in dic)
         {
-            var nullableDictionary = new NullableDictionary<TKey, TValue>()
-            {
-                FallbackValue = defaultValue
-            };
-            foreach (var p in dic)
-            {
-                nullableDictionary[p.Key] = p.Value;
-            }
-
-            return nullableDictionary;
+            nullableDictionary[p.Key] = p.Value;
         }
+
+        return nullableDictionary;
     }
 }

+ 26 - 27
Masuit.Tools.Abstractions/Extensions/BaseType/IPAddressExtensions.cs

@@ -1,35 +1,34 @@
 using System.Net;
 using System.Net.Sockets;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class IPAddressExtensions
 {
-    public static class IPAddressExtensions
+    /// <summary>
+    /// 判断IP是否是私有地址
+    /// </summary>
+    /// <param name="ip"></param>
+    /// <returns></returns>
+    public static bool IsPrivateIP(this IPAddress ip)
     {
-        /// <summary>
-        /// 判断IP是否是私有地址
-        /// </summary>
-        /// <param name="ip"></param>
-        /// <returns></returns>
-        public static bool IsPrivateIP(this IPAddress ip)
+        if (IPAddress.IsLoopback(ip)) return true;
+        ip = ip.IsIPv4MappedToIPv6 ? ip.MapToIPv4() : ip;
+        byte[] bytes = ip.GetAddressBytes();
+        return ip.AddressFamily switch
         {
-            if (IPAddress.IsLoopback(ip)) return true;
-            ip = ip.IsIPv4MappedToIPv6 ? ip.MapToIPv4() : ip;
-            byte[] bytes = ip.GetAddressBytes();
-            return ip.AddressFamily switch
-            {
-                AddressFamily.InterNetwork when bytes[0] == 10 => true,
-                AddressFamily.InterNetwork when bytes[0] == 100 && bytes[1] >= 64 && bytes[1] <= 127 => true,
-                AddressFamily.InterNetwork when bytes[0] == 169 && bytes[1] == 254 => true,
-                AddressFamily.InterNetwork when bytes[0] == 172 && bytes[1] == 16 => true,
-                AddressFamily.InterNetwork when bytes[0] == 192 && bytes[1] == 88 && bytes[2] == 99 => true,
-                AddressFamily.InterNetwork when bytes[0] == 192 && bytes[1] == 168 => true,
-                AddressFamily.InterNetwork when bytes[0] == 198 && bytes[1] == 18 => true,
-                AddressFamily.InterNetwork when bytes[0] == 198 && bytes[1] == 51 && bytes[2] == 100 => true,
-                AddressFamily.InterNetwork when bytes[0] == 203 && bytes[1] == 0 && bytes[2] == 113 => true,
-                AddressFamily.InterNetwork when bytes[0] >= 233 => true,
-                AddressFamily.InterNetworkV6 when ip.IsIPv6Teredo || ip.IsIPv6LinkLocal || ip.IsIPv6Multicast || ip.IsIPv6SiteLocal || bytes[0] == 0 || bytes[0] >= 252 => true,
-                _ => false
-            };
-        }
+            AddressFamily.InterNetwork when bytes[0] == 10 => true,
+            AddressFamily.InterNetwork when bytes[0] == 100 && bytes[1] >= 64 && bytes[1] <= 127 => true,
+            AddressFamily.InterNetwork when bytes[0] == 169 && bytes[1] == 254 => true,
+            AddressFamily.InterNetwork when bytes[0] == 172 && bytes[1] == 16 => true,
+            AddressFamily.InterNetwork when bytes[0] == 192 && bytes[1] == 88 && bytes[2] == 99 => true,
+            AddressFamily.InterNetwork when bytes[0] == 192 && bytes[1] == 168 => true,
+            AddressFamily.InterNetwork when bytes[0] == 198 && bytes[1] == 18 => true,
+            AddressFamily.InterNetwork when bytes[0] == 198 && bytes[1] == 51 && bytes[2] == 100 => true,
+            AddressFamily.InterNetwork when bytes[0] == 203 && bytes[1] == 0 && bytes[2] == 113 => true,
+            AddressFamily.InterNetwork when bytes[0] >= 233 => true,
+            AddressFamily.InterNetworkV6 when ip.IsIPv6Teredo || ip.IsIPv6LinkLocal || ip.IsIPv6Multicast || ip.IsIPv6SiteLocal || bytes[0] == 0 || bytes[0] >= 252 => true,
+            _ => false
+        };
     }
 }

+ 22 - 24
Masuit.Tools.Abstractions/Extensions/BaseType/IntExtensions.cs

@@ -1,31 +1,29 @@
 using Masuit.Tools.Strings;
 using System;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class IntExtensions
 {
-    public static class IntExtensions
+    /// <summary>
+    /// 转换成字节数组
+    /// </summary>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    public static byte[] GetBytes(this int value)
     {
-        /// <summary>
-        /// 转换成字节数组
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static byte[] GetBytes(this int value)
-        {
-            return BitConverter.GetBytes(value);
-        }
-
-        /// <summary>
-        /// 十进制转任意进制
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="newBase">进制</param>
-        /// <returns></returns>
-        public static string ToBase(this int num, byte newBase)
-        {
-            var nf = new NumberFormater(newBase);
-            return nf.ToString(num);
-        }
+        return BitConverter.GetBytes(value);
+    }
 
+    /// <summary>
+    /// 十进制转任意进制
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="newBase">进制</param>
+    /// <returns></returns>
+    public static string ToBase(this int num, byte newBase)
+    {
+        var nf = new NumberFormater(newBase);
+        return nf.ToString(num);
     }
-}
+}

+ 41 - 42
Masuit.Tools.Abstractions/Extensions/BaseType/LongExtensions.cs

@@ -1,52 +1,51 @@
 using Masuit.Tools.Strings;
 using System;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class LongExtensions
 {
-    public static class LongExtensions
+    /// <summary>
+    /// 十进制转任意进制
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="newBase">进制</param>
+    /// <returns></returns>
+    public static string ToBase(this long num, byte newBase)
     {
-        /// <summary>
-        /// 十进制转任意进制
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="newBase">进制</param>
-        /// <returns></returns>
-        public static string ToBase(this long num, byte newBase)
-        {
-            var nf = new NumberFormater(newBase);
-            return nf.ToString(num);
-        }
+        var nf = new NumberFormater(newBase);
+        return nf.ToString(num);
+    }
 
-        /// <summary>
-        /// 转换成字节数组
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static byte[] GetBytes(this long value)
-        {
-            return BitConverter.GetBytes(value);
-        }
+    /// <summary>
+    /// 转换成字节数组
+    /// </summary>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    public static byte[] GetBytes(this long value)
+    {
+        return BitConverter.GetBytes(value);
+    }
 
-        /// <summary>
-        /// 十进制转任意进制
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="newBase">进制</param>
-        /// <returns></returns>
-        public static string ToBase(this ulong num, byte newBase)
-        {
-            var nf = new NumberFormater(newBase);
-            return nf.ToString(num);
-        }
+    /// <summary>
+    /// 十进制转任意进制
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="newBase">进制</param>
+    /// <returns></returns>
+    public static string ToBase(this ulong num, byte newBase)
+    {
+        var nf = new NumberFormater(newBase);
+        return nf.ToString(num);
+    }
 
-        /// <summary>
-        /// 转换成字节数组
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static byte[] GetBytes(this ulong value)
-        {
-            return BitConverter.GetBytes(value);
-        }
+    /// <summary>
+    /// 转换成字节数组
+    /// </summary>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    public static byte[] GetBytes(this ulong value)
+    {
+        return BitConverter.GetBytes(value);
     }
 }

+ 316 - 323
Masuit.Tools.Abstractions/Extensions/BaseType/ObjectExtensions.cs

@@ -8,423 +8,416 @@ using Masuit.Tools.Dynamics;
 using Masuit.Tools.Reflection;
 using Newtonsoft.Json.Linq;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+/// <summary>
+/// 对象扩展
+/// </summary>
+public static class ObjectExtensions
 {
+    private static readonly MethodInfo CloneMethod = typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);
+
     /// <summary>
-    /// 对象扩展
+    /// 是否是基本数据类型
     /// </summary>
-    public static class ObjectExtensions
+    /// <param name="type"></param>
+    /// <returns></returns>
+    public static bool IsPrimitive(this Type type)
     {
-        private static readonly MethodInfo CloneMethod = typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);
-
-        /// <summary>
-        /// 是否是基本数据类型
-        /// </summary>
-        /// <param name="type"></param>
-        /// <returns></returns>
-        public static bool IsPrimitive(this Type type)
+        if (type == typeof(string))
         {
-            if (type == typeof(string))
-            {
-                return true;
-            }
-
-            return type.IsValueType && type.IsPrimitive;
+            return true;
         }
 
-        /// <summary>
-        /// 判断类型是否是常见的简单类型
-        /// </summary>
-        /// <param name="type"></param>
-        /// <returns></returns>
-        public static bool IsSimpleType(this Type type)
+        return type.IsValueType && type.IsPrimitive;
+    }
+
+    /// <summary>
+    /// 判断类型是否是常见的简单类型
+    /// </summary>
+    /// <param name="type"></param>
+    /// <returns></returns>
+    public static bool IsSimpleType(this Type type)
+    {
+        //IsPrimitive 判断是否为基础类型。
+        //基元类型为 Boolean、 Byte、 SByte、 Int16、 UInt16、 Int32、 UInt32、 Int64、 UInt64、 IntPtr、 UIntPtr、 Char、 Double 和 Single。
+        var t = Nullable.GetUnderlyingType(type) ?? type;
+        return t.IsPrimitive || t.IsEnum || t == typeof(decimal) || t == typeof(string) || t == typeof(Guid) || t == typeof(TimeSpan) || t == typeof(Uri);
+    }
+
+    /// <summary>
+    /// 是否是常见类型的 数组形式 类型
+    /// </summary>
+    /// <param name="type"></param>
+    /// <returns></returns>
+    public static bool IsSimpleArrayType(this Type type)
+    {
+        return type.IsArray && Type.GetType(type.FullName!.Trim('[', ']')).IsSimpleType();
+    }
+
+    /// <summary>
+    /// 是否是常见类型的 泛型形式 类型
+    /// </summary>
+    /// <param name="type"></param>
+    /// <returns></returns>
+    public static bool IsSimpleListType(this Type type)
+    {
+        type = Nullable.GetUnderlyingType(type) ?? type;
+        return type.IsGenericType && type.GetGenericArguments().Length == 1 && type.GetGenericArguments().FirstOrDefault().IsSimpleType();
+    }
+
+    /// <summary>
+    /// 是否是默认值
+    /// </summary>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    public static bool IsDefaultValue(this object value)
+    {
+        if (value == default)
         {
-            //IsPrimitive 判断是否为基础类型。
-            //基元类型为 Boolean、 Byte、 SByte、 Int16、 UInt16、 Int32、 UInt32、 Int64、 UInt64、 IntPtr、 UIntPtr、 Char、 Double 和 Single。
-            var t = Nullable.GetUnderlyingType(type) ?? type;
-            return t.IsPrimitive || t.IsEnum || t == typeof(decimal) || t == typeof(string) || t == typeof(Guid) || t == typeof(TimeSpan) || t == typeof(Uri);
+            return true;
         }
 
-        /// <summary>
-        /// 是否是常见类型的 数组形式 类型
-        /// </summary>
-        /// <param name="type"></param>
-        /// <returns></returns>
-        public static bool IsSimpleArrayType(this Type type)
+        return value switch
         {
-            return type.IsArray && Type.GetType(type.FullName!.Trim('[', ']')).IsSimpleType();
-        }
+            byte s => s == 0,
+            sbyte s => s == 0,
+            short s => s == 0,
+            char s => s == 0,
+            bool s => s,
+            ushort s => s == 0,
+            int s => s == 0,
+            uint s => s == 0,
+            long s => s == 0,
+            ulong s => s == 0,
+            decimal s => s == 0,
+            float s => s == 0,
+            double s => s == 0,
+            Enum s => Equals(s, Enum.GetValues(value.GetType()).GetValue(0)),
+            DateTime s => s == DateTime.MinValue,
+            DateTimeOffset s => s == DateTimeOffset.MinValue,
+            Guid g => g == Guid.Empty,
+            ValueType => Activator.CreateInstance(value.GetType()).Equals(value),
+            _ => false
+        };
+    }
 
-        /// <summary>
-        /// 是否是常见类型的 泛型形式 类型
-        /// </summary>
-        /// <param name="type"></param>
-        /// <returns></returns>
-        public static bool IsSimpleListType(this Type type)
+    /// <summary>
+    /// 深克隆
+    /// </summary>
+    /// <param name="originalObject"></param>
+    /// <returns></returns>
+    public static object DeepClone(this object originalObject)
+    {
+        return InternalCopy(originalObject, new Dictionary<object, object>(new ReferenceEqualityComparer()));
+    }
+
+    /// <summary>
+    /// 深克隆
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="original"></param>
+    /// <returns></returns>
+    public static T DeepClone<T>(this T original)
+    {
+        return (T)DeepClone((object)original);
+    }
+
+    private static object InternalCopy(object originalObject, IDictionary<object, object> visited)
+    {
+        if (originalObject == null)
         {
-            type = Nullable.GetUnderlyingType(type) ?? type;
-            return type.IsGenericType && type.GetGenericArguments().Length == 1 && type.GetGenericArguments().FirstOrDefault().IsSimpleType();
+            return null;
         }
 
-        /// <summary>
-        /// 是否是默认值
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static bool IsDefaultValue(this object value)
+        var typeToReflect = originalObject.GetType();
+        if (IsPrimitive(typeToReflect))
         {
-            if (value == default)
-            {
-                return true;
-            }
-
-            return value switch
-            {
-                byte s => s == 0,
-                sbyte s => s == 0,
-                short s => s == 0,
-                char s => s == 0,
-                bool s => s,
-                ushort s => s == 0,
-                int s => s == 0,
-                uint s => s == 0,
-                long s => s == 0,
-                ulong s => s == 0,
-                decimal s => s == 0,
-                float s => s == 0,
-                double s => s == 0,
-                Enum s => Equals(s, Enum.GetValues(value.GetType()).GetValue(0)),
-                DateTime s => s == DateTime.MinValue,
-                DateTimeOffset s => s == DateTimeOffset.MinValue,
-                Guid g => g == Guid.Empty,
-                ValueType => Activator.CreateInstance(value.GetType()).Equals(value),
-                _ => false
-            };
+            return originalObject;
         }
 
-        /// <summary>
-        /// 深克隆
-        /// </summary>
-        /// <param name="originalObject"></param>
-        /// <returns></returns>
-        public static object DeepClone(this object originalObject)
+        if (visited.TryGetValue(originalObject, out var copy))
         {
-            return InternalCopy(originalObject, new Dictionary<object, object>(new ReferenceEqualityComparer()));
+            return copy;
         }
 
-        /// <summary>
-        /// 深克隆
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="original"></param>
-        /// <returns></returns>
-        public static T DeepClone<T>(this T original)
+        if (typeof(Delegate).IsAssignableFrom(typeToReflect))
         {
-            return (T)DeepClone((object)original);
+            return null;
         }
 
-        private static object InternalCopy(object originalObject, IDictionary<object, object> visited)
+        var cloneObject = CloneMethod.Invoke(originalObject, null);
+        if (typeToReflect.IsArray)
         {
-            if (originalObject == null)
+            var arrayType = typeToReflect.GetElementType();
+            if (!IsPrimitive(arrayType))
             {
-                return null;
+                Array clonedArray = (Array)cloneObject;
+                clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
             }
+        }
 
-            var typeToReflect = originalObject.GetType();
-            if (IsPrimitive(typeToReflect))
-            {
-                return originalObject;
-            }
+        visited.Add(originalObject, cloneObject);
+        CopyFields(originalObject, visited, cloneObject, typeToReflect);
+        RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
+        return cloneObject;
+    }
 
-            if (visited.TryGetValue(originalObject, out var copy))
-            {
-                return copy;
-            }
+    private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
+    {
+        if (typeToReflect.BaseType != null)
+        {
+            RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
+            CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
+        }
+    }
 
-            if (typeof(Delegate).IsAssignableFrom(typeToReflect))
+    private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, IReflect typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
+    {
+        foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
+        {
+            if (filter != null && !filter(fieldInfo))
             {
-                return null;
+                continue;
             }
 
-            var cloneObject = CloneMethod.Invoke(originalObject, null);
-            if (typeToReflect.IsArray)
+            if (IsPrimitive(fieldInfo.FieldType) || fieldInfo.IsInitOnly)
             {
-                var arrayType = typeToReflect.GetElementType();
-                if (!IsPrimitive(arrayType))
-                {
-                    Array clonedArray = (Array)cloneObject;
-                    clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
-                }
+                continue;
             }
 
-            visited.Add(originalObject, cloneObject);
-            CopyFields(originalObject, visited, cloneObject, typeToReflect);
-            RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
-            return cloneObject;
+            var originalFieldValue = fieldInfo.GetValue(originalObject);
+            var clonedFieldValue = InternalCopy(originalFieldValue, visited);
+            fieldInfo.SetValue(cloneObject, clonedFieldValue);
         }
+    }
 
-        private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
+    /// <summary>
+    /// 判断是否为null,null或0长度都返回true
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    public static bool IsNullOrEmpty<T>(this T value)
+        where T : class
+    {
+        return value switch
         {
-            if (typeToReflect.BaseType != null)
-            {
-                RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
-                CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
-            }
-        }
+            null => true,
+            string s => string.IsNullOrWhiteSpace(s),
+            IEnumerable list => !list.GetEnumerator().MoveNext(),
+            _ => false
+        };
+    }
+
+    /// <summary>
+    /// 转成非null
+    /// </summary>
+    /// <param name="s"></param>
+    /// <param name="value">为空时的替换值</param>
+    /// <returns></returns>
+    public static T IfNull<T>(this T s, in T value)
+    {
+        return s ?? value;
+    }
+
+    /// <summary>
+    /// 转换成json字符串
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <param name="setting"></param>
+    /// <returns></returns>
+    public static string ToJsonString(this object obj, JsonSerializerSettings setting = null)
+    {
+        if (obj == null) return string.Empty;
+        return JsonConvert.SerializeObject(obj, setting);
+    }
+
+    /// <summary>
+    /// json反序列化成对象
+    /// </summary>
+    public static T FromJson<T>(this string json, JsonSerializerSettings setting = null)
+    {
+        return string.IsNullOrEmpty(json) ? default : JsonConvert.DeserializeObject<T>(json, setting);
+    }
+
+    /// <summary>
+    /// 链式操作
+    /// </summary>
+    /// <typeparam name="T1"></typeparam>
+    /// <typeparam name="T2"></typeparam>
+    /// <param name="source"></param>
+    /// <param name="action"></param>
+    public static T2 Next<T1, T2>(this T1 source, Func<T1, T2> action)
+    {
+        return action(source);
+    }
 
-        private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, IReflect typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
+    /// <summary>
+    /// 将对象转换成字典
+    /// </summary>
+    /// <param name="value"></param>
+    public static Dictionary<string, object> ToDictionary(this object value)
+    {
+        var dictionary = new Dictionary<string, object>();
+        if (value != null)
         {
-            foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
+            if (value is IDictionary dic)
             {
-                if (filter != null && !filter(fieldInfo))
+                foreach (DictionaryEntry e in dic)
                 {
-                    continue;
+                    dictionary.Add(e.Key.ToString(), e.Value);
                 }
-
-                if (IsPrimitive(fieldInfo.FieldType) || fieldInfo.IsInitOnly)
-                {
-                    continue;
-                }
-
-                var originalFieldValue = fieldInfo.GetValue(originalObject);
-                var clonedFieldValue = InternalCopy(originalFieldValue, visited);
-                fieldInfo.SetValue(cloneObject, clonedFieldValue);
+                return dictionary;
             }
-        }
 
-        /// <summary>
-        /// 判断是否为null,null或0长度都返回true
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static bool IsNullOrEmpty<T>(this T value)
-          where T : class
-        {
-            return value switch
+            foreach (var property in value.GetType().GetProperties())
             {
-                null => true,
-                string s => string.IsNullOrWhiteSpace(s),
-                IEnumerable list => !list.GetEnumerator().MoveNext(),
-                _ => false
-            };
-        }
-
-        /// <summary>
-        /// 转成非null
-        /// </summary>
-        /// <param name="s"></param>
-        /// <param name="value">为空时的替换值</param>
-        /// <returns></returns>
-        public static T IfNull<T>(this T s, in T value)
-        {
-            return s ?? value;
+                var obj = property.GetValue(value, null);
+                dictionary.Add(property.Name, obj);
+            }
         }
 
-        /// <summary>
-        /// 转换成json字符串
-        /// </summary>
-        /// <param name="obj"></param>
-        /// <param name="setting"></param>
-        /// <returns></returns>
-        public static string ToJsonString(this object obj, JsonSerializerSettings setting = null)
-        {
-            if (obj == null) return string.Empty;
-            return JsonConvert.SerializeObject(obj, setting);
-        }
+        return dictionary;
+    }
 
-        /// <summary>
-        /// json反序列化成对象
-        /// </summary>
-        public static T FromJson<T>(this string json, JsonSerializerSettings setting = null)
+    /// <summary>
+    /// 将对象转换成字典
+    /// </summary>
+    /// <param name="value"></param>
+    public static Dictionary<string, string> ToDictionary(this JObject value)
+    {
+        var dictionary = new Dictionary<string, string>();
+        if (value != null)
         {
-            if (string.IsNullOrEmpty(json))
+            using var enumerator = value.GetEnumerator();
+            while (enumerator.MoveNext())
             {
-                return default;
+                var obj = enumerator.Current.Value ?? string.Empty;
+                dictionary.Add(enumerator.Current.Key, obj + string.Empty);
             }
-            return JsonConvert.DeserializeObject<T>(json, setting);
         }
 
-        /// <summary>
-        /// 链式操作
-        /// </summary>
-        /// <typeparam name="T1"></typeparam>
-        /// <typeparam name="T2"></typeparam>
-        /// <param name="source"></param>
-        /// <param name="action"></param>
-        public static T2 Next<T1, T2>(this T1 source, Func<T1, T2> action)
-        {
-            return action(source);
-        }
-
-        /// <summary>
-        /// 将对象转换成字典
-        /// </summary>
-        /// <param name="value"></param>
-        public static Dictionary<string, object> ToDictionary(this object value)
-        {
-            var dictionary = new Dictionary<string, object>();
-            if (value != null)
-            {
-                if (value is IDictionary dic)
-                {
-                    foreach (DictionaryEntry e in dic)
-                    {
-                        dictionary.Add(e.Key.ToString(), e.Value);
-                    }
-                    return dictionary;
-                }
-
-                foreach (var property in value.GetType().GetProperties())
-                {
-                    var obj = property.GetValue(value, null);
-                    dictionary.Add(property.Name, obj);
-                }
-            }
+        return dictionary;
+    }
 
-            return dictionary;
-        }
+    /// <summary>
+    /// 对象转换成动态类型
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <returns></returns>
+    public static dynamic ToDynamic(this object obj)
+    {
+        return DynamicFactory.WithObject(obj);
+    }
 
-        /// <summary>
-        /// 将对象转换成字典
-        /// </summary>
-        /// <param name="value"></param>
-        public static Dictionary<string, string> ToDictionary(this JObject value)
+    /// <summary>
+    /// 多个对象的属性值合并
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="a"></param>
+    /// <param name="b"></param>
+    /// <param name="others"></param>
+    public static T Merge<T>(this T a, T b, params T[] others) where T : class
+    {
+        foreach (var item in new[] { b }.Concat(others))
         {
-            var dictionary = new Dictionary<string, string>();
-            if (value != null)
+            var dic = item.ToDictionary();
+            foreach (var p in dic.Where(p => a.GetProperty(p.Key).IsDefaultValue()))
             {
-                var enumerator = value.GetEnumerator();
-                while (enumerator.MoveNext())
-                {
-                    var obj = enumerator.Current.Value ?? string.Empty;
-                    dictionary.Add(enumerator.Current.Key, obj + string.Empty);
-                }
+                a.SetProperty(p.Key, p.Value);
             }
-
-            return dictionary;
         }
 
-        /// <summary>
-        /// 对象转换成动态类型
-        /// </summary>
-        /// <param name="obj"></param>
-        /// <returns></returns>
-        public static dynamic ToDynamic(this object obj)
-        {
-            return DynamicFactory.WithObject(obj);
-        }
+        return a;
+    }
 
-        /// <summary>
-        /// 多个对象的属性值合并
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="a"></param>
-        /// <param name="b"></param>
-        /// <param name="others"></param>
-        public static T Merge<T>(this T a, T b, params T[] others) where T : class
+    /// <summary>
+    /// 多个对象的属性值合并
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    public static T Merge<T>(this IEnumerable<T> objects) where T : class
+    {
+        var list = objects as List<T> ?? objects.ToList();
+        switch (list.Count)
         {
-            foreach (var item in new[] { b }.Concat(others))
-            {
-                var dic = item.ToDictionary();
-                foreach (var p in dic.Where(p => a.GetProperty(p.Key).IsDefaultValue()))
-                {
-                    a.SetProperty(p.Key, p.Value);
-                }
-            }
+            case 0:
+                return null;
 
-            return a;
+            case 1:
+                return list[0];
         }
 
-        /// <summary>
-        /// 多个对象的属性值合并
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        public static T Merge<T>(this IEnumerable<T> objects) where T : class
+        foreach (var item in list.Skip(1))
         {
-            var list = objects as List<T> ?? objects.ToList();
-            if (list.Count == 0)
+            var dic = item.ToDictionary();
+            foreach (var p in dic.Where(p => list[0].GetProperty(p.Key).IsDefaultValue()))
             {
-                return null;
+                list[0].SetProperty(p.Key, p.Value);
             }
+        }
 
-            if (list.Count == 1)
-            {
-                return list[0];
-            }
+        return list[0];
+    }
+}
 
-            foreach (var item in list.Skip(1))
-            {
-                var dic = item.ToDictionary();
-                foreach (var p in dic.Where(p => list[0].GetProperty(p.Key).IsDefaultValue()))
-                {
-                    list[0].SetProperty(p.Key, p.Value);
-                }
-            }
+internal class ReferenceEqualityComparer : EqualityComparer<object>
+{
+    public override bool Equals(object x, object y)
+    {
+        return ReferenceEquals(x, y);
+    }
 
-            return list[0];
-        }
+    public override int GetHashCode(object obj)
+    {
+        return obj is null ? 0 : obj.GetHashCode();
     }
+}
 
-    internal class ReferenceEqualityComparer : EqualityComparer<object>
+internal static class ArrayExtensions
+{
+    public static void ForEach(this Array array, Action<Array, int[]> action)
     {
-        public override bool Equals(object x, object y)
+        if (array.LongLength == 0)
         {
-            return ReferenceEquals(x, y);
+            return;
         }
 
-        public override int GetHashCode(object obj)
-        {
-            if (obj is null) return 0;
-            return obj.GetHashCode();
-        }
+        ArrayTraverse walker = new ArrayTraverse(array);
+        do action(array, walker.Position);
+        while (walker.Step());
     }
 
-    internal static class ArrayExtensions
+    internal class ArrayTraverse
     {
-        public static void ForEach(this Array array, Action<Array, int[]> action)
+        public int[] Position;
+        private readonly int[] _maxLengths;
+
+        public ArrayTraverse(Array array)
         {
-            if (array.LongLength == 0)
+            _maxLengths = new int[array.Rank];
+            for (int i = 0; i < array.Rank; ++i)
             {
-                return;
+                _maxLengths[i] = array.GetLength(i) - 1;
             }
-
-            ArrayTraverse walker = new ArrayTraverse(array);
-            do action(array, walker.Position);
-            while (walker.Step());
+            Position = new int[array.Rank];
         }
 
-        internal class ArrayTraverse
+        public bool Step()
         {
-            public int[] Position;
-            private readonly int[] _maxLengths;
-
-            public ArrayTraverse(Array array)
-            {
-                _maxLengths = new int[array.Rank];
-                for (int i = 0; i < array.Rank; ++i)
-                {
-                    _maxLengths[i] = array.GetLength(i) - 1;
-                }
-                Position = new int[array.Rank];
-            }
-
-            public bool Step()
+            for (int i = 0; i < Position.Length; ++i)
             {
-                for (int i = 0; i < Position.Length; ++i)
+                if (Position[i] < _maxLengths[i])
                 {
-                    if (Position[i] < _maxLengths[i])
+                    Position[i]++;
+                    for (int j = 0; j < i; j++)
                     {
-                        Position[i]++;
-                        for (int j = 0; j < i; j++)
-                        {
-                            Position[j] = 0;
-                        }
-                        return true;
+                        Position[j] = 0;
                     }
+                    return true;
                 }
-                return false;
             }
+            return false;
         }
     }
 }

+ 26 - 27
Masuit.Tools.Abstractions/Extensions/BaseType/RandomExtensions.cs

@@ -1,33 +1,32 @@
 using System;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class RandomExtensions
 {
-    public static class RandomExtensions
+    /// <summary>
+    /// 生成真正的随机数
+    /// </summary>
+    /// <param name="r"></param>
+    /// <param name="maxValue"></param>
+    /// <returns></returns>
+    public static int StrictNext(this Random r, int maxValue = int.MaxValue)
     {
-        /// <summary>
-        /// 生成真正的随机数
-        /// </summary>
-        /// <param name="r"></param>
-        /// <param name="maxValue"></param>
-        /// <returns></returns>
-        public static int StrictNext(this Random r, int maxValue = int.MaxValue)
-        {
-            return new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0)).Next(maxValue);
-        }
+        return new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0)).Next(maxValue);
+    }
 
-        /// <summary>
-        /// 产生正态分布的随机数
-        /// </summary>
-        /// <param name="rand"></param>
-        /// <param name="mean">均值</param>
-        /// <param name="stdDev">方差</param>
-        /// <returns></returns>
-        public static double NextGauss(this Random rand, double mean, double stdDev)
-        {
-            double u1 = 1.0 - rand.NextDouble();
-            double u2 = 1.0 - rand.NextDouble();
-            double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
-            return mean + stdDev * randStdNormal;
-        }
+    /// <summary>
+    /// 产生正态分布的随机数
+    /// </summary>
+    /// <param name="rand"></param>
+    /// <param name="mean">均值</param>
+    /// <param name="stdDev">方差</param>
+    /// <returns></returns>
+    public static double NextGauss(this Random rand, double mean, double stdDev)
+    {
+        double u1 = 1.0 - rand.NextDouble();
+        double u2 = 1.0 - rand.NextDouble();
+        double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
+        return mean + stdDev * randStdNormal;
     }
-}
+}

+ 11 - 12
Masuit.Tools.Abstractions/Extensions/BaseType/ShortExtensions.cs

@@ -1,17 +1,16 @@
 using System;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class ShortExtensions
 {
-    public static class ShortExtensions
+    /// <summary>
+    /// 转换成字节数组
+    /// </summary>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    public static byte[] GetBytes(this short value)
     {
-        /// <summary>
-        /// 转换成字节数组
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static byte[] GetBytes(this short value)
-        {
-            return BitConverter.GetBytes(value);
-        }
+        return BitConverter.GetBytes(value);
     }
-}
+}

+ 259 - 264
Masuit.Tools.Abstractions/Extensions/BaseType/StreamExtensions.cs

@@ -12,336 +12,332 @@ using System.Buffers;
 using System.Runtime.InteropServices;
 #endif
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class StreamExtensions
 {
-    public static class StreamExtensions
+    /// <summary>
+    /// 将流转换为内存流
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <returns></returns>
+    public static PooledMemoryStream SaveAsMemoryStream(this Stream stream)
     {
-        /// <summary>
-        /// 将流转换为内存流
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <returns></returns>
-        public static PooledMemoryStream SaveAsMemoryStream(this Stream stream)
+        if (stream is PooledMemoryStream pooledMemoryStream)
         {
-            if (stream is PooledMemoryStream pooledMemoryStream)
-            {
-                return pooledMemoryStream;
-            }
-
-            stream.Position = 0;
-            var ms = new PooledMemoryStream();
-            stream.CopyTo(ms);
-            stream.Position = 0;
-            return ms;
+            return pooledMemoryStream;
         }
 
-        /// <summary>
-        ///
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <returns></returns>
-        public static byte[] ToArray(this Stream stream)
-        {
-            stream.Position = 0;
-            byte[] bytes = new byte[stream.Length];
-            stream.Read(bytes, 0, bytes.Length);
+        stream.Position = 0;
+        var ms = new PooledMemoryStream();
+        stream.CopyTo(ms);
+        stream.Position = 0;
+        return ms;
+    }
 
-            // 设置当前流的位置为流的开始
-            stream.Seek(0, SeekOrigin.Begin);
-            return bytes;
-        }
+    /// <summary>
+    ///
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <returns></returns>
+    public static byte[] ToArray(this Stream stream)
+    {
+        stream.Position = 0;
+        byte[] bytes = new byte[stream.Length];
+        stream.Read(bytes, 0, bytes.Length);
 
-        /// <summary>
-        /// 流洗码,在流的末端随即增加几个空字节,重要数据请谨慎使用,可能造成流损坏
-        /// </summary>
-        /// <param name="stream"></param>
-        public static void ShuffleCode(this Stream stream)
+        // 设置当前流的位置为流的开始
+        stream.Seek(0, SeekOrigin.Begin);
+        return bytes;
+    }
+
+    /// <summary>
+    /// 流洗码,在流的末端随即增加几个空字节,重要数据请谨慎使用,可能造成流损坏
+    /// </summary>
+    /// <param name="stream"></param>
+    public static void ShuffleCode(this Stream stream)
+    {
+        if (stream.CanWrite && stream.CanSeek)
         {
-            if (stream.CanWrite && stream.CanSeek)
+            var position = stream.Position;
+            stream.Position = stream.Length;
+            for (int i = 0; i < new Random().Next(1, 20); i++)
             {
-                var position = stream.Position;
-                stream.Position = stream.Length;
-                for (int i = 0; i < new Random().Next(1, 20); i++)
-                {
-                    stream.WriteByte(0);
-                }
-                stream.Flush();
-                stream.Position = position;
+                stream.WriteByte(0);
             }
+            stream.Flush();
+            stream.Position = position;
         }
+    }
 
-        /// <summary>
-        /// 读取所有行
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static List<string> ReadAllLines(this StreamReader stream, bool closeAfter = true)
+    /// <summary>
+    /// 读取所有行
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static List<string> ReadAllLines(this StreamReader stream, bool closeAfter = true)
+    {
+        var stringList = new List<string>();
+        while (stream.ReadLine() is { } str)
         {
-            var stringList = new List<string>();
-            string str;
-            while ((str = stream.ReadLine()) != null)
-            {
-                stringList.Add(str);
-            }
-
-            if (closeAfter)
-            {
-                stream.Close();
-                stream.Dispose();
-            }
-            return stringList;
+            stringList.Add(str);
         }
 
-        /// <summary>
-        /// 读取所有行
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static List<string> ReadAllLines(this FileStream stream, Encoding encoding, bool closeAfter = true)
+        if (closeAfter)
         {
-            var stringList = new List<string>();
-            string str;
-            var sr = new StreamReader(stream, encoding);
-            while ((str = sr.ReadLine()) != null)
-            {
-                stringList.Add(str);
-            }
-
-            if (closeAfter)
-            {
-                sr.Close();
-                sr.Dispose();
-                stream.Close();
-                stream.Dispose();
-            }
-
-            return stringList;
+            stream.Close();
+            stream.Dispose();
         }
+        return stringList;
+    }
 
-        /// <summary>
-        /// 读取所有文本
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static string ReadAllText(this FileStream stream, Encoding encoding, bool closeAfter = true)
+    /// <summary>
+    /// 读取所有行
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static List<string> ReadAllLines(this FileStream stream, Encoding encoding, bool closeAfter = true)
+    {
+        var stringList = new List<string>();
+        var sr = new StreamReader(stream, encoding);
+        while (sr.ReadLine() is { } str)
         {
-            var sr = new StreamReader(stream, encoding);
-            var text = sr.ReadToEnd();
-            if (closeAfter)
-            {
-                sr.Close();
-                sr.Dispose();
-                stream.Close();
-                stream.Dispose();
-            }
+            stringList.Add(str);
+        }
 
-            return text;
+        if (closeAfter)
+        {
+            sr.Close();
+            sr.Dispose();
+            stream.Close();
+            stream.Dispose();
         }
 
-        /// <summary>
-        /// 写入所有文本
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="content"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static void WriteAllText(this FileStream stream, string content, Encoding encoding, bool closeAfter = true)
+        return stringList;
+    }
+
+    /// <summary>
+    /// 读取所有文本
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static string ReadAllText(this FileStream stream, Encoding encoding, bool closeAfter = true)
+    {
+        var sr = new StreamReader(stream, encoding);
+        var text = sr.ReadToEnd();
+        if (closeAfter)
         {
-            var sw = new StreamWriter(stream, encoding);
-            stream.SetLength(0);
-            sw.Write(content);
-            if (closeAfter)
-            {
-                sw.Close();
-                sw.Dispose();
-                stream.Close();
-                stream.Dispose();
-            }
+            sr.Close();
+            sr.Dispose();
+            stream.Close();
+            stream.Dispose();
         }
 
-        /// <summary>
-        /// 写入所有文本行
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="lines"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static void WriteAllLines(this FileStream stream, IEnumerable<string> lines, Encoding encoding, bool closeAfter = true)
+        return text;
+    }
+
+    /// <summary>
+    /// 写入所有文本
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="content"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static void WriteAllText(this FileStream stream, string content, Encoding encoding, bool closeAfter = true)
+    {
+        var sw = new StreamWriter(stream, encoding);
+        stream.SetLength(0);
+        sw.Write(content);
+        if (closeAfter)
         {
-            var sw = new StreamWriter(stream, encoding);
-            stream.SetLength(0);
-            foreach (var line in lines)
-            {
-                sw.WriteLine(line);
-            }
+            sw.Close();
+            sw.Dispose();
+            stream.Close();
+            stream.Dispose();
+        }
+    }
 
-            sw.Flush();
-            if (closeAfter)
-            {
-                sw.Close();
-                sw.Dispose();
-                stream.Close();
-                stream.Dispose();
-            }
+    /// <summary>
+    /// 写入所有文本行
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="lines"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static void WriteAllLines(this FileStream stream, IEnumerable<string> lines, Encoding encoding, bool closeAfter = true)
+    {
+        var sw = new StreamWriter(stream, encoding);
+        stream.SetLength(0);
+        foreach (var line in lines)
+        {
+            sw.WriteLine(line);
         }
 
-        /// <summary>
-        /// 共享读写打开文件
-        /// </summary>
-        /// <param name="file"></param>
-        /// <returns></returns>
-        public static FileStream ShareReadWrite(this FileInfo file)
+        sw.Flush();
+        if (closeAfter)
         {
-            return file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
+            sw.Close();
+            sw.Dispose();
+            stream.Close();
+            stream.Dispose();
         }
+    }
 
-        /// <summary>
-        /// 读取所有行
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static async Task<List<string>> ReadAllLinesAsync(this StreamReader stream, bool closeAfter = true)
+    /// <summary>
+    /// 共享读写打开文件
+    /// </summary>
+    /// <param name="file"></param>
+    /// <returns></returns>
+    public static FileStream ShareReadWrite(this FileInfo file)
+    {
+        return file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
+    }
+
+    /// <summary>
+    /// 读取所有行
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static async Task<List<string>> ReadAllLinesAsync(this StreamReader stream, bool closeAfter = true)
+    {
+        var stringList = new List<string>();
+        while (await stream.ReadLineAsync().ConfigureAwait(false) is { } str)
         {
-            var stringList = new List<string>();
-            string str;
-            while ((str = await stream.ReadLineAsync().ConfigureAwait(false)) != null)
-            {
-                stringList.Add(str);
-            }
+            stringList.Add(str);
+        }
 
-            if (closeAfter)
-            {
-                stream.Close();
-                stream.Dispose();
-            }
-            return stringList;
+        if (closeAfter)
+        {
+            stream.Close();
+            stream.Dispose();
         }
+        return stringList;
+    }
 
-        /// <summary>
-        /// 读取所有行
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static async Task<List<string>> ReadAllLinesAsync(this FileStream stream, Encoding encoding, bool closeAfter = true)
+    /// <summary>
+    /// 读取所有行
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static async Task<List<string>> ReadAllLinesAsync(this FileStream stream, Encoding encoding, bool closeAfter = true)
+    {
+        var stringList = new List<string>();
+        var sr = new StreamReader(stream, encoding);
+        while (await sr.ReadLineAsync().ConfigureAwait(false) is { } str)
         {
-            var stringList = new List<string>();
-            string str;
-            var sr = new StreamReader(stream, encoding);
-            while ((str = await sr.ReadLineAsync().ConfigureAwait(false)) != null)
-            {
-                stringList.Add(str);
-            }
+            stringList.Add(str);
+        }
 
-            if (closeAfter)
-            {
-                sr.Close();
-                sr.Dispose();
-                stream.Close();
+        if (closeAfter)
+        {
+            sr.Close();
+            sr.Dispose();
+            stream.Close();
 #if NET5_0_OR_GREATER
                 await stream.DisposeAsync().ConfigureAwait(false);
 #else
-                stream.Dispose();
+            stream.Dispose();
 #endif
-            }
-
-            return stringList;
         }
 
-        /// <summary>
-        /// 读取所有文本
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static async Task<string> ReadAllTextAsync(this FileStream stream, Encoding encoding, bool closeAfter = true)
+        return stringList;
+    }
+
+    /// <summary>
+    /// 读取所有文本
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static async Task<string> ReadAllTextAsync(this FileStream stream, Encoding encoding, bool closeAfter = true)
+    {
+        var sr = new StreamReader(stream, encoding);
+        var text = await sr.ReadToEndAsync().ConfigureAwait(false);
+        if (closeAfter)
         {
-            var sr = new StreamReader(stream, encoding);
-            var text = await sr.ReadToEndAsync().ConfigureAwait(false);
-            if (closeAfter)
-            {
-                sr.Close();
-                sr.Dispose();
-                stream.Close();
+            sr.Close();
+            sr.Dispose();
+            stream.Close();
 #if NET5_0_OR_GREATER
                 await stream.DisposeAsync().ConfigureAwait(false);
 #else
-                stream.Dispose();
+            stream.Dispose();
 #endif
-            }
-
-            return text;
         }
 
-        /// <summary>
-        /// 写入所有文本
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="content"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static async Task WriteAllTextAsync(this FileStream stream, string content, Encoding encoding, bool closeAfter = true)
+        return text;
+    }
+
+    /// <summary>
+    /// 写入所有文本
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="content"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static async Task WriteAllTextAsync(this FileStream stream, string content, Encoding encoding, bool closeAfter = true)
+    {
+        var sw = new StreamWriter(stream, encoding);
+        stream.SetLength(0);
+        await sw.WriteAsync(content).ConfigureAwait(false);
+        await sw.FlushAsync().ConfigureAwait(false);
+        if (closeAfter)
         {
-            var sw = new StreamWriter(stream, encoding);
-            stream.SetLength(0);
-            await sw.WriteAsync(content).ConfigureAwait(false);
-            await sw.FlushAsync().ConfigureAwait(false);
-            if (closeAfter)
-            {
-                sw.Close();
-                stream.Close();
+            sw.Close();
+            stream.Close();
 #if NET5_0_OR_GREATER
                 await sw.DisposeAsync().ConfigureAwait(false);
                 await stream.DisposeAsync().ConfigureAwait(false);
 #else
-                sw.Dispose();
-                stream.Dispose();
+            sw.Dispose();
+            stream.Dispose();
 #endif
-            }
         }
+    }
 
-        /// <summary>
-        /// 写入所有文本行
-        /// </summary>
-        /// <param name="stream"></param>
-        /// <param name="lines"></param>
-        /// <param name="encoding"></param>
-        /// <param name="closeAfter">读取完毕后关闭流</param>
-        /// <returns></returns>
-        public static async Task WriteAllLinesAsync(this FileStream stream, IEnumerable<string> lines, Encoding encoding, bool closeAfter = true)
+    /// <summary>
+    /// 写入所有文本行
+    /// </summary>
+    /// <param name="stream"></param>
+    /// <param name="lines"></param>
+    /// <param name="encoding"></param>
+    /// <param name="closeAfter">读取完毕后关闭流</param>
+    /// <returns></returns>
+    public static async Task WriteAllLinesAsync(this FileStream stream, IEnumerable<string> lines, Encoding encoding, bool closeAfter = true)
+    {
+        var sw = new StreamWriter(stream, encoding);
+        stream.SetLength(0);
+        foreach (var line in lines)
         {
-            var sw = new StreamWriter(stream, encoding);
-            stream.SetLength(0);
-            foreach (var line in lines)
-            {
-                await sw.WriteLineAsync(line).ConfigureAwait(false);
-            }
+            await sw.WriteLineAsync(line).ConfigureAwait(false);
+        }
 
-            await sw.FlushAsync().ConfigureAwait(false);
-            if (closeAfter)
-            {
-                sw.Close();
-                stream.Close();
+        await sw.FlushAsync().ConfigureAwait(false);
+        if (closeAfter)
+        {
+            sw.Close();
+            stream.Close();
 #if NET5_0_OR_GREATER
                 await sw.DisposeAsync().ConfigureAwait(false);
                 await stream.DisposeAsync().ConfigureAwait(false);
 #else
-                sw.Dispose();
-                stream.Dispose();
+            sw.Dispose();
+            stream.Dispose();
 #endif
-            }
         }
+    }
 
 #if NET5_0_OR_GREATER
 
@@ -360,5 +356,4 @@ namespace Masuit.Tools
             return bytes;
         }
 #endif
-    }
 }

+ 915 - 919
Masuit.Tools.Abstractions/Extensions/BaseType/StringExtensions.cs

@@ -16,928 +16,924 @@ using System.Threading.Tasks;
 
 namespace Masuit.Tools
 {
-	public static partial class StringExtensions
-	{
-		public static string Join(this IEnumerable<string> strs, string separate = ", ", bool removeEmptyEntry = false) => string.Join(separate, removeEmptyEntry ? strs.Where(s => !string.IsNullOrEmpty(s)) : strs);
-
-		public static string Join<T>(this IEnumerable<T> strs, string separate = ", ", bool removeEmptyEntry = false) => string.Join(separate, removeEmptyEntry ? strs.Where(t => t != null) : strs);
-
-		/// <summary>
-		/// 字符串转时间
-		/// </summary>
-		/// <param name="value"></param>
-		/// <returns></returns>
-		public static DateTime ToDateTime(this string value)
-		{
-			DateTime.TryParse(value, out var result);
-			return result;
-		}
-
-		/// <summary>
-		/// 字符串转Guid
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static Guid ToGuid(this string s)
-		{
-			return Guid.Parse(s);
-		}
-
-		/// <summary>
-		/// 根据正则替换
-		/// </summary>
-		/// <param name="input"></param>
-		/// <param name="regex">正则表达式</param>
-		/// <param name="replacement">新内容</param>
-		/// <returns></returns>
-		public static string Replace(this string input, Regex regex, string replacement)
-		{
-			return regex.Replace(input, replacement);
-		}
-
-		/// <summary>
-		/// 生成唯一短字符串
-		/// </summary>
-		/// <param name="str"></param>
-		/// <param name="chars">可用字符数数量,0-9,a-z,A-Z</param>
-		/// <returns></returns>
-		public static string CreateShortToken(this string str, byte chars = 36)
-		{
-			var nf = new NumberFormater(chars);
-			return nf.ToString((DateTime.Now.Ticks - 630822816000000000) * 100 + Stopwatch.GetTimestamp() % 100);
-		}
-
-		/// <summary>
-		/// 任意进制转十进制
-		/// </summary>
-		/// <param name="str"></param>
-		/// <param name="base">进制</param>
-		/// <returns></returns>
-		public static long FromBase(this string str, byte @base)
-		{
-			var nf = new NumberFormater(@base);
-			return nf.FromString(str);
-		}
-
-		/// <summary>
-		/// 任意进制转大数十进制
-		/// </summary>
-		/// <param name="str"></param>
-		/// <param name="base">进制</param>
-		/// <returns></returns>
-		public static BigInteger FromBaseBig(this string str, byte @base)
-		{
-			var nf = new NumberFormater(@base);
-			return nf.FromStringBig(str);
-		}
-
-		#region 检测字符串中是否包含列表中的关键词
-
-		/// <summary>
-		/// 检测字符串中是否包含列表中的关键词(快速匹配)
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="keys">关键词列表</param>
-		/// <param name="ignoreCase">忽略大小写</param>
-		/// <returns></returns>
-		public static bool Contains(this string s, IEnumerable<string> keys, bool ignoreCase = true)
-		{
-			if (keys is not ICollection<string> array)
-			{
-				array = keys.ToArray();
-			}
-
-			if (array.Count == 0 || string.IsNullOrEmpty(s))
-			{
-				return false;
-			}
-
-			return ignoreCase ? array.Any(item => s.IndexOf(item, StringComparison.InvariantCultureIgnoreCase) >= 0) : array.Any(s.Contains);
-		}
-
-		/// <summary>
-		/// 检测字符串中是否包含列表中的关键词(安全匹配)
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="keys">关键词列表</param>
-		/// <param name="ignoreCase">忽略大小写</param>
-		/// <returns></returns>
-		public static bool ContainsSafety(this string s, IEnumerable<string> keys, bool ignoreCase = true)
-		{
-			if (keys is not ICollection<string> array)
-			{
-				array = keys.ToArray();
-			}
-
-			if (array.Count == 0 || string.IsNullOrEmpty(s))
-			{
-				return false;
-			}
-
-			bool flag = false;
-			if (ignoreCase)
-			{
-				foreach (var item in array)
-				{
-					if (s.Contains(item))
-					{
-						flag = true;
-					}
-				}
-			}
-			else
-			{
-				foreach (var item in array)
-				{
-					if (s.IndexOf(item, StringComparison.InvariantCultureIgnoreCase) >= 0)
-					{
-						flag = true;
-					}
-				}
-			}
-
-			return flag;
-		}
-
-		/// <summary>
-		/// 检测字符串中是否以列表中的关键词结尾
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="keys">关键词列表</param>
-		/// <param name="ignoreCase">忽略大小写</param>
-		/// <returns></returns>
-		public static bool EndsWith(this string s, IEnumerable<string> keys, bool ignoreCase = true)
-		{
-			if (keys is not ICollection<string> array)
-			{
-				array = keys.ToArray();
-			}
-
-			if (array.Count == 0 || string.IsNullOrEmpty(s))
-			{
-				return false;
-			}
-
-			var pattern = $"({array.Select(Regex.Escape).Join("|")})$";
-			return ignoreCase ? Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase) : Regex.IsMatch(s, pattern);
-		}
-
-		/// <summary>
-		/// 检测字符串中是否以列表中的关键词开始
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="keys">关键词列表</param>
-		/// <param name="ignoreCase">忽略大小写</param>
-		/// <returns></returns>
-		public static bool StartsWith(this string s, IEnumerable<string> keys, bool ignoreCase = true)
-		{
-			if (keys is not ICollection<string> array)
-			{
-				array = keys.ToArray();
-			}
-
-			if (array.Count == 0 || string.IsNullOrEmpty(s))
-			{
-				return false;
-			}
-
-			var pattern = $"^({array.Select(Regex.Escape).Join("|")})";
-			return ignoreCase ? Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase) : Regex.IsMatch(s, pattern);
-		}
-
-		/// <summary>
-		/// 检测字符串中是否包含列表中的关键词
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="regex">关键词列表</param>
-		/// <param name="ignoreCase">忽略大小写</param>
-		/// <returns></returns>
-		public static bool RegexMatch(this string s, string regex, bool ignoreCase = true)
-		{
-			if (string.IsNullOrEmpty(regex) || string.IsNullOrEmpty(s))
-			{
-				return false;
-			}
-
-			if (ignoreCase)
-			{
-				return Regex.IsMatch(s, regex, RegexOptions.IgnoreCase);
-			}
-
-			return Regex.IsMatch(s, regex);
-		}
-
-		/// <summary>
-		/// 检测字符串中是否包含列表中的关键词
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="regex">关键词列表</param>
-		/// <returns></returns>
-		public static bool RegexMatch(this string s, Regex regex) => !string.IsNullOrEmpty(s) && regex.IsMatch(s);
-
-		#endregion 检测字符串中是否包含列表中的关键词
-
-		/// <summary>
-		/// 判断字符串是否为空或""
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static bool IsNullOrEmpty(this string s)
-		{
-			return string.IsNullOrWhiteSpace(s) || s.Equals("null", StringComparison.CurrentCultureIgnoreCase);
-		}
-
-		/// <summary>
-		/// 判断字符串不为空或""
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static bool NotNullOrEmpty(this string s)
-		{
-			return !string.IsNullOrWhiteSpace(s) && !s.Equals("null", StringComparison.CurrentCultureIgnoreCase);
-		}
-
-		/// <summary>
-		/// 转成非null
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static string AsNotNull(this string s)
-		{
-			return string.IsNullOrEmpty(s) ? "" : s;
-		}
-
-		/// <summary>
-		/// 转成非null
-		/// </summary>
-		/// <param name="s"></param>
-		/// <param name="value">为空时的替换值</param>
-		/// <returns></returns>
-		public static string IfNullOrEmpty(this string s, string value)
-		{
-			return string.IsNullOrEmpty(s) ? value : s;
-		}
-
-		/// <summary>
-		/// 转成非null
-		/// </summary>
-		/// <param name="s"></param>
-		/// <param name="valueFactory">为空时的替换值函数</param>
-		/// <returns></returns>
-		public static string IfNullOrEmpty(this string s, Func<string> valueFactory)
-		{
-			return string.IsNullOrEmpty(s) ? valueFactory() : s;
-		}
-
-		/// <summary>
-		/// 字符串掩码
-		/// </summary>
-		/// <param name="s">字符串</param>
-		/// <param name="mask">掩码符</param>
-		/// <returns></returns>
-		public static string Mask(this string s, char mask = '*')
-		{
-			if (string.IsNullOrWhiteSpace(s?.Trim()))
-			{
-				return s;
-			}
-
-			s = s.Trim();
-			string masks = mask.ToString().PadLeft(4, mask);
-			return s.Length switch
-			{
-				>= 11 => Regex.Replace(s, "(.{3}).*(.{4})", $"$1{masks}$2"),
-				10 => Regex.Replace(s, "(.{3}).*(.{3})", $"$1{masks}$2"),
-				9 => Regex.Replace(s, "(.{2}).*(.{3})", $"$1{masks}$2"),
-				8 => Regex.Replace(s, "(.{2}).*(.{2})", $"$1{masks}$2"),
-				7 => Regex.Replace(s, "(.{1}).*(.{2})", $"$1{masks}$2"),
-				6 => Regex.Replace(s, "(.{1}).*(.{1})", $"$1{masks}$2"),
-				_ => Regex.Replace(s, "(.{1}).*", $"$1{masks}")
-			};
-		}
-
-		#region Email
-
-		/// <summary>
-		/// 匹配Email
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="valid">是否验证有效性</param>
-		/// <returns>匹配对象;是否匹配成功,若返回true,则会得到一个Match对象,否则为null</returns>
-		public static (bool isMatch, Match match) MatchEmail(this string s, bool valid = false)
-		{
-			if (string.IsNullOrEmpty(s) || s.Length < 7)
-			{
-				return (false, null);
-			}
-
-			var match = Regex.Match(s, @"[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n]+");
-			var isMatch = match.Success;
-			if (isMatch && valid)
-			{
-				var nslookup = new LookupClient();
-				var task = nslookup.Query(s.Split('@')[1], QueryType.MX).Answers.MxRecords().SelectAsync(r => Dns.GetHostAddressesAsync(r.Exchange.Value).ContinueWith(t =>
-				{
-					if (t.IsCanceled || t.IsFaulted)
-					{
-						return new[]
-						{
-							IPAddress.Loopback
-						};
-					}
-
-					return t.Result;
-				}));
-				isMatch = task.Result.SelectMany(a => a).Any(ip => !ip.IsPrivateIP());
-			}
-
-			return (isMatch, match);
-		}
-
-		/// <summary>
-		/// 匹配Email
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="valid">是否验证有效性</param>
-		/// <returns>匹配对象;是否匹配成功,若返回true,则会得到一个Match对象,否则为null</returns>
-		public static async Task<(bool isMatch, Match match)> MatchEmailAsync(this string s, bool valid = false)
-		{
-			if (string.IsNullOrEmpty(s) || s.Length < 7)
-			{
-				return (false, null);
-			}
-
-			var match = Regex.Match(s, @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
-			var isMatch = match.Success;
-			if (isMatch && valid)
-			{
-				var nslookup = new LookupClient();
-				using var cts = new CancellationTokenSource(100);
-				var query = await nslookup.QueryAsync(s.Split('@')[1], QueryType.MX, cancellationToken: cts.Token);
-				var result = await query.Answers.MxRecords().SelectAsync(r => Dns.GetHostAddressesAsync(r.Exchange.Value).ContinueWith(t =>
-				{
-					if (t.IsCanceled || t.IsFaulted)
-					{
-						return new[] { IPAddress.Loopback };
-					}
-
-					return t.Result;
-				}));
-				isMatch = result.SelectMany(a => a).Any(ip => !ip.IsPrivateIP());
-			}
-
-			return (isMatch, match);
-		}
-
-		/// <summary>
-		/// 邮箱掩码
-		/// </summary>
-		/// <param name="s">邮箱</param>
-		/// <param name="mask">掩码</param>
-		/// <returns></returns>
-		public static string MaskEmail(this string s, char mask = '*')
-		{
-			var index = s.LastIndexOf("@");
-			var oldValue = s.Substring(0, index);
-			return !MatchEmail(s).isMatch ? s : s.Replace(oldValue, Mask(oldValue, mask));
-		}
-
-		#endregion Email
-
-		#region 匹配完整的URL
-
-		/// <summary>
-		/// 匹配完整格式的URL
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
-		/// <returns>匹配对象</returns>
-		public static Uri MatchUrl(this string s, out bool isMatch)
-		{
-			try
-			{
-				var uri = new Uri(s);
-				isMatch = Dns.GetHostAddresses(uri.Host).Any(ip => !ip.IsPrivateIP());
-				return uri;
-			}
-			catch
-			{
-				isMatch = false;
-				return null;
-			}
-		}
-
-		/// <summary>
-		/// 匹配完整格式的URL
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <returns>是否匹配成功</returns>
-		public static bool MatchUrl(this string s)
-		{
-			MatchUrl(s, out var isMatch);
-			return isMatch;
-		}
-
-		#endregion 匹配完整的URL
-
-		#region 权威校验身份证号码
-
-		/// <summary>
-		/// 根据GB11643-1999标准权威校验中国身份证号码的合法性
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <returns>是否匹配成功</returns>
-		public static bool MatchIdentifyCard(this string s)
-		{
-			return s.Length switch
-			{
-				18 => CheckChinaID18(s),
-				15 => CheckChinaID15(s),
-				_ => false
-			};
-		}
-
-		private static readonly string[] ChinaIDProvinceCodes = {
-			 "11", "12", "13", "14", "15",
-			 "21", "22", "23",
-			 "31", "32", "33", "34", "35", "36", "37",
-			 "41", "42", "43", "44", "45", "46",
-			 "50", "51", "52", "53", "54",
-			 "61", "62", "63", "64", "65",
-			"71",
-			"81",
-			"82",
-			"91"
-		};
-
-		private static bool CheckChinaID18(string ID)
-		{
-			ID = ID.ToUpper();
-			Match m = Regex.Match(ID, @"\d{17}[\dX]", RegexOptions.IgnoreCase);
-			if (!m.Success)
-			{
-				return false;
-			}
-
-			if (!ChinaIDProvinceCodes.Contains(ID.Substring(0, 2)))
-			{
-				return false;
-			}
-
-			CultureInfo zhCN = new CultureInfo("zh-CN", true);
-			if (!DateTime.TryParseExact(ID.Substring(6, 8), "yyyyMMdd", zhCN, DateTimeStyles.None, out DateTime birthday))
-			{
-				return false;
-			}
-
-			if (!birthday.In(new DateTime(1800, 1, 1), DateTime.Today))
-			{
-				return false;
-			}
-			int[] factors = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
-			int sum = 0;
-			for (int i = 0; i < 17; i++)
-			{
-				sum += (ID[i] - '0') * factors[i];
-			}
-
-			int n = (12 - sum % 11) % 11;
-			return n < 10 ? ID[17] - '0' == n : ID[17].Equals('X');
-		}
-
-		private static bool CheckChinaID15(string ID)
-		{
-			Match m = Regex.Match(ID, @"\d{15}", RegexOptions.IgnoreCase);
-			if (!m.Success)
-			{
-				return false;
-			}
-
-			if (!ChinaIDProvinceCodes.Contains(ID.Substring(0, 2)))
-			{
-				return false;
-			}
-
-			CultureInfo zhCN = new CultureInfo("zh-CN", true);
-			if (!DateTime.TryParseExact("19" + ID.Substring(6, 6), "yyyyMMdd", zhCN, DateTimeStyles.None, out DateTime birthday))
-			{
-				return false;
-			}
-
-			return birthday.In(new DateTime(1800, 1, 1), new DateTime(2000, 1, 1));
-		}
-
-		#endregion 权威校验身份证号码
-
-		#region IP地址
-
-		/// <summary>
-		/// 校验IP地址的正确性,同时支持IPv4和IPv6
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
-		/// <returns>匹配对象</returns>
-		public static IPAddress MatchInetAddress(this string s, out bool isMatch)
-		{
-			isMatch = IPAddress.TryParse(s, out var ip);
-			return ip;
-		}
-
-		/// <summary>
-		/// 校验IP地址的正确性,同时支持IPv4和IPv6
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <returns>是否匹配成功</returns>
-		public static bool MatchInetAddress(this string s)
-		{
-			MatchInetAddress(s, out var success);
-			return success;
-		}
-
-		/// <summary>
-		/// IP地址转换成数字
-		/// </summary>
-		/// <param name="addr">IP地址</param>
-		/// <returns>数字,输入无效IP地址返回0</returns>
-		public static uint IPToID(this string addr)
-		{
-			if (!IPAddress.TryParse(addr, out var ip))
-			{
-				return 0;
-			}
-
-			byte[] bInt = ip.GetAddressBytes();
-			if (BitConverter.IsLittleEndian)
-			{
-				Array.Reverse(bInt);
-			}
-
-			return BitConverter.ToUInt32(bInt, 0);
-		}
-
-		/// <summary>
-		/// IP地址转换成数字
-		/// </summary>
-		/// <param name="ip">IP地址</param>
-		/// <returns>数字,输入无效IP地址返回0</returns>
-		public static uint ToUInt32(this IPAddress ip)
-		{
-			byte[] bInt = ip.GetAddressBytes();
-			if (BitConverter.IsLittleEndian)
-			{
-				Array.Reverse(bInt);
-			}
-
-			return BitConverter.ToUInt32(bInt, 0);
-		}
-
-		/// <summary>
-		/// 判断IP是否是私有地址
-		/// </summary>
-		/// <param name="ip"></param>
-		/// <returns></returns>
-		public static bool IsPrivateIP(this string ip)
-		{
-			var address = MatchInetAddress(ip, out var b);
-			return b && address.IsPrivateIP();
-		}
-
-		/// <summary>
-		/// 判断IP地址在不在某个IP地址段
-		/// </summary>
-		/// <param name="input">需要判断的IP地址</param>
-		/// <param name="begin">起始地址</param>
-		/// <param name="ends">结束地址</param>
-		/// <returns></returns>
-		public static bool IpAddressInRange(this string input, string begin, string ends)
-		{
-			uint current = input.IPToID();
-			return current >= begin.IPToID() && current <= ends.IPToID();
-		}
-
-		/// <summary>
-		/// 判断IP地址在不在某个IP地址段
-		/// </summary>
-		/// <param name="input">需要判断的IP地址</param>
-		/// <param name="begin">起始地址</param>
-		/// <param name="ends">结束地址</param>
-		/// <returns></returns>
-		public static bool IpAddressInRange(this IPAddress input, IPAddress begin, IPAddress ends)
-		{
-			uint current = input.ToUInt32();
-			return current >= begin.ToUInt32() && current <= ends.ToUInt32();
-		}
-
-		#endregion IP地址
-
-		#region 校验手机号码的正确性
-
-		/// <summary>
-		/// 匹配手机号码
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <returns>是否匹配成功</returns>
-		public static bool MatchPhoneNumber(this string s)
-		{
-			return !string.IsNullOrEmpty(s) && s.Length == 11 && s[0] == '1' && (s[1] > '2' || s[1] <= '9') && long.TryParse(s, out _);
-		}
-
-		/// <summary>
-		/// 匹配固话号码
-		/// </summary>
-		/// <param name="s">源字符串</param>
-		/// <returns>是否匹配成功</returns>
-		public static bool MatchLandline(this string s)
-		{
-			return Regex.IsMatch(s, @"^0\d{2,3}(?:-?\d{8}|-?\d{7})$");
-		}
-
-		#endregion 校验手机号码的正确性
-
-		#region Url
-
-		/// <summary>
-		/// 判断url是否是外部地址
-		/// </summary>
-		/// <param name="url"></param>
-		/// <returns></returns>
-		public static bool IsExternalAddress(this string url)
-		{
-			var uri = new Uri(url);
-			switch (uri.HostNameType)
-			{
-				case UriHostNameType.Dns:
-					var ipHostEntry = Dns.GetHostEntry(uri.DnsSafeHost);
-					if (ipHostEntry.AddressList.Where(ipAddress => ipAddress.AddressFamily == AddressFamily.InterNetwork).Any(ipAddress => !ipAddress.IsPrivateIP()))
-					{
-						return true;
-					}
-
-					break;
-
-				case UriHostNameType.IPv4:
-					return !IPAddress.Parse(uri.DnsSafeHost).IsPrivateIP();
-			}
-
-			return false;
-		}
-
-		#endregion Url
-
-		/// <summary>
-		/// 转换成字节数组
-		/// </summary>
-		/// <param name="this"></param>
-		/// <returns></returns>
-		public static byte[] ToByteArray(this string @this)
-		{
-			return Encoding.UTF8.GetBytes(@this);
-		}
-
-		#region Crc32
-
-		/// <summary>
-		/// 获取字符串crc32签名
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static string Crc32(this string s)
-		{
-			return string.Join(string.Empty, new Security.Crc32().ComputeHash(Encoding.UTF8.GetBytes(s)).Select(b => b.ToString("x2")));
-		}
-
-		/// <summary>
-		/// 获取字符串crc64签名
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static string Crc64(this string s)
-		{
-			return string.Join(string.Empty, new Security.Crc64().ComputeHash(Encoding.UTF8.GetBytes(s)).Select(b => b.ToString("x2")));
-		}
-
-		#endregion Crc32
-
-		#region 权威校验中国专利申请号/专利号
-
-		/// <summary>
-		/// 中国专利申请号(授权以后就是专利号)由两种组成
-		/// 2003年9月30号以前的9位(不带校验位是8号),校验位之前可能还会有一个点,例如:00262311, 002623110 或 00262311.0
-		/// 2003年10月1号以后的13位(不带校验位是12号),校验位之前可能还会有一个点,例如:200410018477, 2004100184779 或200410018477.9
-		/// http://www.sipo.gov.cn/docs/pub/old/wxfw/zlwxxxggfw/hlwzljsxt/hlwzljsxtsyzn/201507/P020150713610193194682.pdf
-		/// 上面的文档中均不包括校验算法,但是下面的校验算法没有问题
-		/// </summary>
-		/// <param name="patnum">源字符串</param>
-		/// <returns>是否匹配成功</returns>
-		public static bool MatchCNPatentNumber(this string patnum)
-		{
-			Regex patnumWithCheckbitPattern = new Regex(@"^
+    public static partial class StringExtensions
+    {
+        public static string Join(this IEnumerable<string> strs, string separate = ", ", bool removeEmptyEntry = false) => string.Join(separate, removeEmptyEntry ? strs.Where(s => !string.IsNullOrEmpty(s)) : strs);
+
+        public static string Join<T>(this IEnumerable<T> strs, string separate = ", ", bool removeEmptyEntry = false) => string.Join(separate, removeEmptyEntry ? strs.Where(t => t != null) : strs);
+
+        /// <summary>
+        /// 字符串转时间
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static DateTime ToDateTime(this string value)
+        {
+            DateTime.TryParse(value, out var result);
+            return result;
+        }
+
+        /// <summary>
+        /// 字符串转Guid
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static Guid ToGuid(this string s)
+        {
+            return Guid.Parse(s);
+        }
+
+        /// <summary>
+        /// 根据正则替换
+        /// </summary>
+        /// <param name="input"></param>
+        /// <param name="regex">正则表达式</param>
+        /// <param name="replacement">新内容</param>
+        /// <returns></returns>
+        public static string Replace(this string input, Regex regex, string replacement)
+        {
+            return regex.Replace(input, replacement);
+        }
+
+        /// <summary>
+        /// 生成唯一短字符串
+        /// </summary>
+        /// <param name="str"></param>
+        /// <param name="chars">可用字符数数量,0-9,a-z,A-Z</param>
+        /// <returns></returns>
+        public static string CreateShortToken(this string str, byte chars = 36)
+        {
+            var nf = new NumberFormater(chars);
+            return nf.ToString((DateTime.Now.Ticks - 630822816000000000) * 100 + Stopwatch.GetTimestamp() % 100);
+        }
+
+        /// <summary>
+        /// 任意进制转十进制
+        /// </summary>
+        /// <param name="str"></param>
+        /// <param name="base">进制</param>
+        /// <returns></returns>
+        public static long FromBase(this string str, byte @base)
+        {
+            var nf = new NumberFormater(@base);
+            return nf.FromString(str);
+        }
+
+        /// <summary>
+        /// 任意进制转大数十进制
+        /// </summary>
+        /// <param name="str"></param>
+        /// <param name="base">进制</param>
+        /// <returns></returns>
+        public static BigInteger FromBaseBig(this string str, byte @base)
+        {
+            var nf = new NumberFormater(@base);
+            return nf.FromStringBig(str);
+        }
+
+        #region 检测字符串中是否包含列表中的关键词
+
+        /// <summary>
+        /// 检测字符串中是否包含列表中的关键词(快速匹配)
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="keys">关键词列表</param>
+        /// <param name="ignoreCase">忽略大小写</param>
+        /// <returns></returns>
+        public static bool Contains(this string s, IEnumerable<string> keys, bool ignoreCase = true)
+        {
+            if (keys is not ICollection<string> array)
+            {
+                array = keys.ToArray();
+            }
+
+            if (array.Count == 0 || string.IsNullOrEmpty(s))
+            {
+                return false;
+            }
+
+            return ignoreCase ? array.Any(item => s.IndexOf(item, StringComparison.InvariantCultureIgnoreCase) >= 0) : array.Any(s.Contains);
+        }
+
+        /// <summary>
+        /// 检测字符串中是否包含列表中的关键词(安全匹配)
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="keys">关键词列表</param>
+        /// <param name="ignoreCase">忽略大小写</param>
+        /// <returns></returns>
+        public static bool ContainsSafety(this string s, IEnumerable<string> keys, bool ignoreCase = true)
+        {
+            if (keys is not ICollection<string> array)
+            {
+                array = keys.ToArray();
+            }
+
+            if (array.Count == 0 || string.IsNullOrEmpty(s))
+            {
+                return false;
+            }
+
+            bool flag = false;
+            if (ignoreCase)
+            {
+                foreach (var item in array)
+                {
+                    if (s.Contains(item))
+                    {
+                        flag = true;
+                    }
+                }
+            }
+            else
+            {
+                foreach (var item in array)
+                {
+                    if (s.IndexOf(item, StringComparison.InvariantCultureIgnoreCase) >= 0)
+                    {
+                        flag = true;
+                    }
+                }
+            }
+
+            return flag;
+        }
+
+        /// <summary>
+        /// 检测字符串中是否以列表中的关键词结尾
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="keys">关键词列表</param>
+        /// <param name="ignoreCase">忽略大小写</param>
+        /// <returns></returns>
+        public static bool EndsWith(this string s, IEnumerable<string> keys, bool ignoreCase = true)
+        {
+            if (keys is not ICollection<string> array)
+            {
+                array = keys.ToArray();
+            }
+
+            if (array.Count == 0 || string.IsNullOrEmpty(s))
+            {
+                return false;
+            }
+
+            var pattern = $"({array.Select(Regex.Escape).Join("|")})$";
+            return ignoreCase ? Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase) : Regex.IsMatch(s, pattern);
+        }
+
+        /// <summary>
+        /// 检测字符串中是否以列表中的关键词开始
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="keys">关键词列表</param>
+        /// <param name="ignoreCase">忽略大小写</param>
+        /// <returns></returns>
+        public static bool StartsWith(this string s, IEnumerable<string> keys, bool ignoreCase = true)
+        {
+            if (keys is not ICollection<string> array)
+            {
+                array = keys.ToArray();
+            }
+
+            if (array.Count == 0 || string.IsNullOrEmpty(s))
+            {
+                return false;
+            }
+
+            var pattern = $"^({array.Select(Regex.Escape).Join("|")})";
+            return ignoreCase ? Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase) : Regex.IsMatch(s, pattern);
+        }
+
+        /// <summary>
+        /// 检测字符串中是否包含列表中的关键词
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="regex">关键词列表</param>
+        /// <param name="ignoreCase">忽略大小写</param>
+        /// <returns></returns>
+        public static bool RegexMatch(this string s, string regex, bool ignoreCase = true)
+        {
+            if (string.IsNullOrEmpty(regex) || string.IsNullOrEmpty(s))
+            {
+                return false;
+            }
+
+            if (ignoreCase)
+            {
+                return Regex.IsMatch(s, regex, RegexOptions.IgnoreCase);
+            }
+
+            return Regex.IsMatch(s, regex);
+        }
+
+        /// <summary>
+        /// 检测字符串中是否包含列表中的关键词
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="regex">关键词列表</param>
+        /// <returns></returns>
+        public static bool RegexMatch(this string s, Regex regex) => !string.IsNullOrEmpty(s) && regex.IsMatch(s);
+
+        #endregion 检测字符串中是否包含列表中的关键词
+
+        /// <summary>
+        /// 判断字符串是否为空或""
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static bool IsNullOrEmpty(this string s)
+        {
+            return string.IsNullOrWhiteSpace(s) || s.Equals("null", StringComparison.CurrentCultureIgnoreCase);
+        }
+
+        /// <summary>
+        /// 判断字符串不为空或""
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static bool NotNullOrEmpty(this string s)
+        {
+            return !string.IsNullOrWhiteSpace(s) && !s.Equals("null", StringComparison.CurrentCultureIgnoreCase);
+        }
+
+        /// <summary>
+        /// 转成非null
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static string AsNotNull(this string s)
+        {
+            return string.IsNullOrEmpty(s) ? "" : s;
+        }
+
+        /// <summary>
+        /// 转成非null
+        /// </summary>
+        /// <param name="s"></param>
+        /// <param name="value">为空时的替换值</param>
+        /// <returns></returns>
+        public static string IfNullOrEmpty(this string s, string value)
+        {
+            return string.IsNullOrEmpty(s) ? value : s;
+        }
+
+        /// <summary>
+        /// 转成非null
+        /// </summary>
+        /// <param name="s"></param>
+        /// <param name="valueFactory">为空时的替换值函数</param>
+        /// <returns></returns>
+        public static string IfNullOrEmpty(this string s, Func<string> valueFactory)
+        {
+            return string.IsNullOrEmpty(s) ? valueFactory() : s;
+        }
+
+        /// <summary>
+        /// 字符串掩码
+        /// </summary>
+        /// <param name="s">字符串</param>
+        /// <param name="mask">掩码符</param>
+        /// <returns></returns>
+        public static string Mask(this string s, char mask = '*')
+        {
+            if (string.IsNullOrWhiteSpace(s?.Trim()))
+            {
+                return s;
+            }
+
+            s = s.Trim();
+            string masks = mask.ToString().PadLeft(4, mask);
+            return s.Length switch
+            {
+                >= 11 => Regex.Replace(s, "(.{3}).*(.{4})", $"$1{masks}$2"),
+                10 => Regex.Replace(s, "(.{3}).*(.{3})", $"$1{masks}$2"),
+                9 => Regex.Replace(s, "(.{2}).*(.{3})", $"$1{masks}$2"),
+                8 => Regex.Replace(s, "(.{2}).*(.{2})", $"$1{masks}$2"),
+                7 => Regex.Replace(s, "(.{1}).*(.{2})", $"$1{masks}$2"),
+                6 => Regex.Replace(s, "(.{1}).*(.{1})", $"$1{masks}$2"),
+                _ => Regex.Replace(s, "(.{1}).*", $"$1{masks}")
+            };
+        }
+
+        #region Email
+
+        /// <summary>
+        /// 匹配Email
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="valid">是否验证有效性</param>
+        /// <returns>匹配对象;是否匹配成功,若返回true,则会得到一个Match对象,否则为null</returns>
+        public static (bool isMatch, Match match) MatchEmail(this string s, bool valid = false)
+        {
+            if (string.IsNullOrEmpty(s) || s.Length < 7)
+            {
+                return (false, null);
+            }
+
+            var match = Regex.Match(s, @"[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n]+");
+            var isMatch = match.Success;
+            if (isMatch && valid)
+            {
+                var nslookup = new LookupClient();
+                var task = nslookup.Query(s.Split('@')[1], QueryType.MX).Answers.MxRecords().SelectAsync(r => Dns.GetHostAddressesAsync(r.Exchange.Value).ContinueWith(t =>
+                {
+                    if (t.IsCanceled || t.IsFaulted)
+                    {
+                        return new[]
+                        {
+                            IPAddress.Loopback
+                        };
+                    }
+
+                    return t.Result;
+                }));
+                isMatch = task.Result.SelectMany(a => a).Any(ip => !ip.IsPrivateIP());
+            }
+
+            return (isMatch, match);
+        }
+
+        /// <summary>
+        /// 匹配Email
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="valid">是否验证有效性</param>
+        /// <returns>匹配对象;是否匹配成功,若返回true,则会得到一个Match对象,否则为null</returns>
+        public static async Task<(bool isMatch, Match match)> MatchEmailAsync(this string s, bool valid = false)
+        {
+            if (string.IsNullOrEmpty(s) || s.Length < 7)
+            {
+                return (false, null);
+            }
+
+            var match = Regex.Match(s, @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
+            var isMatch = match.Success;
+            if (isMatch && valid)
+            {
+                var nslookup = new LookupClient();
+                using var cts = new CancellationTokenSource(100);
+                var query = await nslookup.QueryAsync(s.Split('@')[1], QueryType.MX, cancellationToken: cts.Token);
+                var result = await query.Answers.MxRecords().SelectAsync(r => Dns.GetHostAddressesAsync(r.Exchange.Value).ContinueWith(t =>
+                {
+                    if (t.IsCanceled || t.IsFaulted)
+                    {
+                        return new[] { IPAddress.Loopback };
+                    }
+
+                    return t.Result;
+                }));
+                isMatch = result.SelectMany(a => a).Any(ip => !ip.IsPrivateIP());
+            }
+
+            return (isMatch, match);
+        }
+
+        /// <summary>
+        /// 邮箱掩码
+        /// </summary>
+        /// <param name="s">邮箱</param>
+        /// <param name="mask">掩码</param>
+        /// <returns></returns>
+        public static string MaskEmail(this string s, char mask = '*')
+        {
+            var index = s.LastIndexOf("@");
+            var oldValue = s.Substring(0, index);
+            return !MatchEmail(s).isMatch ? s : s.Replace(oldValue, Mask(oldValue, mask));
+        }
+
+        #endregion Email
+
+        #region 匹配完整的URL
+
+        /// <summary>
+        /// 匹配完整格式的URL
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
+        /// <returns>匹配对象</returns>
+        public static Uri MatchUrl(this string s, out bool isMatch)
+        {
+            try
+            {
+                var uri = new Uri(s);
+                isMatch = Dns.GetHostAddresses(uri.Host).Any(ip => !ip.IsPrivateIP());
+                return uri;
+            }
+            catch
+            {
+                isMatch = false;
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 匹配完整格式的URL
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <returns>是否匹配成功</returns>
+        public static bool MatchUrl(this string s)
+        {
+            MatchUrl(s, out var isMatch);
+            return isMatch;
+        }
+
+        #endregion 匹配完整的URL
+
+        #region 权威校验身份证号码
+
+        /// <summary>
+        /// 根据GB11643-1999标准权威校验中国身份证号码的合法性
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <returns>是否匹配成功</returns>
+        public static bool MatchIdentifyCard(this string s)
+        {
+            return s.Length switch
+            {
+                18 => CheckChinaID18(s),
+                15 => CheckChinaID15(s),
+                _ => false
+            };
+        }
+
+        private static readonly string[] ChinaIDProvinceCodes = {
+             "11", "12", "13", "14", "15",
+             "21", "22", "23",
+             "31", "32", "33", "34", "35", "36", "37",
+             "41", "42", "43", "44", "45", "46",
+             "50", "51", "52", "53", "54",
+             "61", "62", "63", "64", "65",
+            "71",
+            "81",
+            "82",
+            "91"
+        };
+
+        private static bool CheckChinaID18(string ID)
+        {
+            ID = ID.ToUpper();
+            Match m = Regex.Match(ID, @"\d{17}[\dX]", RegexOptions.IgnoreCase);
+            if (!m.Success)
+            {
+                return false;
+            }
+
+            if (!ChinaIDProvinceCodes.Contains(ID.Substring(0, 2)))
+            {
+                return false;
+            }
+
+            CultureInfo zhCN = new CultureInfo("zh-CN", true);
+            if (!DateTime.TryParseExact(ID.Substring(6, 8), "yyyyMMdd", zhCN, DateTimeStyles.None, out DateTime birthday))
+            {
+                return false;
+            }
+
+            if (!birthday.In(new DateTime(1800, 1, 1), DateTime.Today))
+            {
+                return false;
+            }
+            int[] factors = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
+            int sum = 0;
+            for (int i = 0; i < 17; i++)
+            {
+                sum += (ID[i] - '0') * factors[i];
+            }
+
+            int n = (12 - sum % 11) % 11;
+            return n < 10 ? ID[17] - '0' == n : ID[17].Equals('X');
+        }
+
+        private static bool CheckChinaID15(string ID)
+        {
+            Match m = Regex.Match(ID, @"\d{15}", RegexOptions.IgnoreCase);
+            if (!m.Success)
+            {
+                return false;
+            }
+
+            if (!ChinaIDProvinceCodes.Contains(ID.Substring(0, 2)))
+            {
+                return false;
+            }
+
+            CultureInfo zhCN = new CultureInfo("zh-CN", true);
+            if (!DateTime.TryParseExact("19" + ID.Substring(6, 6), "yyyyMMdd", zhCN, DateTimeStyles.None, out DateTime birthday))
+            {
+                return false;
+            }
+
+            return birthday.In(new DateTime(1800, 1, 1), new DateTime(2000, 1, 1));
+        }
+
+        #endregion 权威校验身份证号码
+
+        #region IP地址
+
+        /// <summary>
+        /// 校验IP地址的正确性,同时支持IPv4和IPv6
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
+        /// <returns>匹配对象</returns>
+        public static IPAddress MatchInetAddress(this string s, out bool isMatch)
+        {
+            isMatch = IPAddress.TryParse(s, out var ip);
+            return ip;
+        }
+
+        /// <summary>
+        /// 校验IP地址的正确性,同时支持IPv4和IPv6
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <returns>是否匹配成功</returns>
+        public static bool MatchInetAddress(this string s)
+        {
+            MatchInetAddress(s, out var success);
+            return success;
+        }
+
+        /// <summary>
+        /// IP地址转换成数字
+        /// </summary>
+        /// <param name="addr">IP地址</param>
+        /// <returns>数字,输入无效IP地址返回0</returns>
+        public static uint IPToID(this string addr)
+        {
+            if (!IPAddress.TryParse(addr, out var ip))
+            {
+                return 0;
+            }
+
+            byte[] bInt = ip.GetAddressBytes();
+            if (BitConverter.IsLittleEndian)
+            {
+                Array.Reverse(bInt);
+            }
+
+            return BitConverter.ToUInt32(bInt, 0);
+        }
+
+        /// <summary>
+        /// IP地址转换成数字
+        /// </summary>
+        /// <param name="ip">IP地址</param>
+        /// <returns>数字,输入无效IP地址返回0</returns>
+        public static uint ToUInt32(this IPAddress ip)
+        {
+            byte[] bInt = ip.GetAddressBytes();
+            if (BitConverter.IsLittleEndian)
+            {
+                Array.Reverse(bInt);
+            }
+
+            return BitConverter.ToUInt32(bInt, 0);
+        }
+
+        /// <summary>
+        /// 判断IP是否是私有地址
+        /// </summary>
+        /// <param name="ip"></param>
+        /// <returns></returns>
+        public static bool IsPrivateIP(this string ip)
+        {
+            var address = MatchInetAddress(ip, out var b);
+            return b && address.IsPrivateIP();
+        }
+
+        /// <summary>
+        /// 判断IP地址在不在某个IP地址段
+        /// </summary>
+        /// <param name="input">需要判断的IP地址</param>
+        /// <param name="begin">起始地址</param>
+        /// <param name="ends">结束地址</param>
+        /// <returns></returns>
+        public static bool IpAddressInRange(this string input, string begin, string ends)
+        {
+            uint current = input.IPToID();
+            return current >= begin.IPToID() && current <= ends.IPToID();
+        }
+
+        /// <summary>
+        /// 判断IP地址在不在某个IP地址段
+        /// </summary>
+        /// <param name="input">需要判断的IP地址</param>
+        /// <param name="begin">起始地址</param>
+        /// <param name="ends">结束地址</param>
+        /// <returns></returns>
+        public static bool IpAddressInRange(this IPAddress input, IPAddress begin, IPAddress ends)
+        {
+            uint current = input.ToUInt32();
+            return current >= begin.ToUInt32() && current <= ends.ToUInt32();
+        }
+
+        #endregion IP地址
+
+        #region 校验手机号码的正确性
+
+        /// <summary>
+        /// 匹配手机号码
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <returns>是否匹配成功</returns>
+        public static bool MatchPhoneNumber(this string s)
+        {
+            return !string.IsNullOrEmpty(s) && s.Length == 11 && s[0] == '1' && (s[1] > '2' || s[1] <= '9') && long.TryParse(s, out _);
+        }
+
+        /// <summary>
+        /// 匹配固话号码
+        /// </summary>
+        /// <param name="s">源字符串</param>
+        /// <returns>是否匹配成功</returns>
+        public static bool MatchLandline(this string s)
+        {
+            return Regex.IsMatch(s, @"^0\d{2,3}(?:-?\d{8}|-?\d{7})$");
+        }
+
+        #endregion 校验手机号码的正确性
+
+        #region Url
+
+        /// <summary>
+        /// 判断url是否是外部地址
+        /// </summary>
+        /// <param name="url"></param>
+        /// <returns></returns>
+        public static bool IsExternalAddress(this string url)
+        {
+            var uri = new Uri(url);
+            switch (uri.HostNameType)
+            {
+                case UriHostNameType.Dns:
+                    var ipHostEntry = Dns.GetHostEntry(uri.DnsSafeHost);
+                    if (ipHostEntry.AddressList.Where(ipAddress => ipAddress.AddressFamily == AddressFamily.InterNetwork).Any(ipAddress => !ipAddress.IsPrivateIP()))
+                    {
+                        return true;
+                    }
+
+                    break;
+
+                case UriHostNameType.IPv4:
+                    return !IPAddress.Parse(uri.DnsSafeHost).IsPrivateIP();
+            }
+
+            return false;
+        }
+
+        #endregion Url
+
+        /// <summary>
+        /// 转换成字节数组
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static byte[] ToByteArray(this string @this)
+        {
+            return Encoding.UTF8.GetBytes(@this);
+        }
+
+        #region Crc32
+
+        /// <summary>
+        /// 获取字符串crc32签名
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static string Crc32(this string s)
+        {
+            return string.Join(string.Empty, new Security.Crc32().ComputeHash(Encoding.UTF8.GetBytes(s)).Select(b => b.ToString("x2")));
+        }
+
+        /// <summary>
+        /// 获取字符串crc64签名
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static string Crc64(this string s)
+        {
+            return string.Join(string.Empty, new Security.Crc64().ComputeHash(Encoding.UTF8.GetBytes(s)).Select(b => b.ToString("x2")));
+        }
+
+        #endregion Crc32
+
+        #region 权威校验中国专利申请号/专利号
+
+        /// <summary>
+        /// 中国专利申请号(授权以后就是专利号)由两种组成
+        /// 2003年9月30号以前的9位(不带校验位是8号),校验位之前可能还会有一个点,例如:00262311, 002623110 或 00262311.0
+        /// 2003年10月1号以后的13位(不带校验位是12号),校验位之前可能还会有一个点,例如:200410018477, 2004100184779 或200410018477.9
+        /// http://www.sipo.gov.cn/docs/pub/old/wxfw/zlwxxxggfw/hlwzljsxt/hlwzljsxtsyzn/201507/P020150713610193194682.pdf
+        /// 上面的文档中均不包括校验算法,但是下面的校验算法没有问题
+        /// </summary>
+        /// <param name="patnum">源字符串</param>
+        /// <returns>是否匹配成功</returns>
+        public static bool MatchCNPatentNumber(this string patnum)
+        {
+            Regex patnumWithCheckbitPattern = new Regex(@"^
 (?<!\d)
 (?<patentnum>
-	(?<basenum>
-		(?<year>(?<old>8[5-9]|9[0-9]|0[0-3])|(?<new>[2-9]\d{3}))
-		(?<sn>
-			(?<patenttype>[12389])
-			(?(old)\d{5}|(?(new)\d{7}))
-		)
-	)
-	(?:
-	\.?
-	(?<checkbit>[0-9X])
-	)?
+    (?<basenum>
+        (?<year>(?<old>8[5-9]|9[0-9]|0[0-3])|(?<new>[2-9]\d{3}))
+        (?<sn>
+            (?<patenttype>[12389])
+            (?(old)\d{5}|(?(new)\d{7}))
+        )
+    )
+    (?:
+    \.?
+    (?<checkbit>[0-9X])
+    )?
 )
 (?!\d)
 $", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase | RegexOptions.Multiline);
-			Match m = patnumWithCheckbitPattern.Match(patnum);
-			if (!m.Success)
-			{
-				return false;
-			}
-
-			bool isPatnumTrue = true;
-			patnum = patnum.ToUpper().Replace(".", "");
-			if (patnum.Length == 9 || patnum.Length == 8)
-			{
-				byte[] factors8 = new byte[] { 2, 3, 4, 5, 6, 7, 8, 9 };
-				int year = Convert.ToUInt16(patnum.Substring(0, 2));
-				year += (year >= 85) ? (ushort)1900u : (ushort)2000u;
-				if (year >= 1985 || year <= 2003)
-				{
-					int sum = 0;
-					for (byte i = 0; i < 8; i++)
-					{
-						sum += factors8[i] * (patnum[i] - '0');
-					}
-
-					char checkbit = "0123456789X"[sum % 11];
-					if (patnum.Length == 9)
-					{
-						if (checkbit != patnum[8])
-						{
-							isPatnumTrue = false;
-						}
-					}
-					else
-					{
-						patnum += checkbit;
-					}
-				}
-				else
-				{
-					isPatnumTrue = false;
-				}
-			}
-			else if (patnum.Length == 13 || patnum.Length == 12)
-			{
-				byte[] factors12 = new byte[12] { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };
-				int year = Convert.ToUInt16(patnum.Substring(0, 4));
-				if (year >= 2003 && year <= DateTime.Now.Year)
-				{
-					int sum = 0;
-					for (byte i = 0; i < 12; i++)
-					{
-						sum += factors12[i] * (patnum[i] - '0');
-					}
-
-					char checkbit = "0123456789X"[sum % 11];
-					if (patnum.Length == 13)
-					{
-						if (checkbit != patnum[12])
-						{
-							isPatnumTrue = false;
-						}
-					}
-					else
-					{
-						patnum += checkbit;
-					}
-				}
-				else
-				{
-					isPatnumTrue = false;
-				}
-			}
-			else
-			{
-				isPatnumTrue = false;
-			}
-
-			return isPatnumTrue;
-		}
-
-		#endregion 权威校验中国专利申请号/专利号
-
-		/// <summary>
-		/// 取字符串前{length}个字
-		/// </summary>
-		/// <param name="s"></param>
-		/// <param name="length"></param>
-		/// <returns></returns>
-		public static string Take(this string s, int length)
-		{
-			return s.Length > length ? s.Substring(0, length) : s;
-		}
-
-		/// <summary>
-		/// 对比字符串的汉明距离
-		/// </summary>
-		/// <param name="this"></param>
-		/// <param name="that"></param>
-		/// <returns></returns>
-		public static int HammingDistance(this string @this, string that) => new SimHash(@this).HammingDistance(new SimHash(that));
-
-		/// <summary>
-		/// 匹配字符串是否包含emoji字符
-		/// </summary>
-		/// <param name="s"></param>
-		/// <returns></returns>
-		public static bool MatchEmoji(this string s)
-		{
-			return Regex.IsMatch(s, @"(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])");
-		}
-
-		/// <summary>
-		/// 获取字符串的字符数
-		/// </summary>
-		/// <param name="str"></param>
-		/// <returns></returns>
-		public static int CharacterCount(this string str)
-		{
-			var enumerator = StringInfo.GetTextElementEnumerator(str);
-			int length = 0;
-			while (enumerator.MoveNext())
-			{
-				length++;
-			}
-
-			return length;
-		}
-
-		/// <summary>
-		/// 获取字符串的字节数
-		/// </summary>
-		/// <param name="str"></param>
-		/// <returns></returns>
-		public static int BytesCount(this string str)
-		{
-			return Encoding.UTF8.GetByteCount(str);
-		}
-
-		/// <summary>
-		/// 转半角(DBC case)
-		/// </summary>
-		/// <param name="input">任意字符串</param>
-		/// <returns>半角字符串</returns>
-		///<remarks>
-		///全角空格为12288,半角空格为32(此处不必转空格)
-		///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
-		///</remarks>
-		public static string ToDBC(this string input)
-		{
-			char[] c = input.ToCharArray();
-			for (int i = 0; i < c.Length; i++)
-			{
-				if (c[i] == 12288)
-				{
-					c[i] = (char)32;
-					continue;
-				}
-
-				if (c[i] > 65280 && c[i] < 65375)
-				{
-					c[i] = (char)(c[i] - 65248);
-				}
-			}
-
-			return new string(c);
-		}
-
-		/// <summary>
-		/// 转全角(SBC case)
-		/// </summary>
-		/// <param name="input">任意字符串</param>
-		/// <returns>全角字符串</returns>
-		///<remarks>
-		///全角空格为12288,半角空格为32
-		///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
-		///</remarks>
-		public static string ToSBC(this string input)
-		{
-			//半角转全角:
-			var c = input.ToCharArray();
-			for (int i = 0; i < c.Length; i++)
-			{
-				if (c[i] == 32)
-				{
-					c[i] = (char)12288;
-					continue;
-				}
-				if (c[i] < 127 && c[i] > 32)
-				{
-					c[i] = (char)(c[i] + 65248);
-				}
-			}
-			return new string(c);
-		}
-	}
+            Match m = patnumWithCheckbitPattern.Match(patnum);
+            if (!m.Success)
+            {
+                return false;
+            }
+
+            bool isPatnumTrue = true;
+            patnum = patnum.ToUpper().Replace(".", "");
+            if (patnum.Length == 9 || patnum.Length == 8)
+            {
+                byte[] factors8 = new byte[] { 2, 3, 4, 5, 6, 7, 8, 9 };
+                int year = Convert.ToUInt16(patnum.Substring(0, 2));
+                year += (year >= 85) ? (ushort)1900u : (ushort)2000u;
+                if (year >= 1985 || year <= 2003)
+                {
+                    int sum = 0;
+                    for (byte i = 0; i < 8; i++)
+                    {
+                        sum += factors8[i] * (patnum[i] - '0');
+                    }
+
+                    char checkbit = "0123456789X"[sum % 11];
+                    if (patnum.Length == 9)
+                    {
+                        if (checkbit != patnum[8])
+                        {
+                            isPatnumTrue = false;
+                        }
+                    }
+                }
+                else
+                {
+                    isPatnumTrue = false;
+                }
+            }
+            else if (patnum.Length == 13 || patnum.Length == 12)
+            {
+                byte[] factors12 = { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };
+                int year = Convert.ToUInt16(patnum.Substring(0, 4));
+                if (year >= 2003 && year <= DateTime.Now.Year)
+                {
+                    int sum = 0;
+                    for (byte i = 0; i < 12; i++)
+                    {
+                        sum += factors12[i] * (patnum[i] - '0');
+                    }
+
+                    char checkbit = "0123456789X"[sum % 11];
+                    if (patnum.Length == 13)
+                    {
+                        if (checkbit != patnum[12])
+                        {
+                            isPatnumTrue = false;
+                        }
+                    }
+                    else
+                    {
+                        patnum += checkbit;
+                    }
+                }
+                else
+                {
+                    isPatnumTrue = false;
+                }
+            }
+            else
+            {
+                isPatnumTrue = false;
+            }
+
+            return isPatnumTrue;
+        }
+
+        #endregion 权威校验中国专利申请号/专利号
+
+        /// <summary>
+        /// 取字符串前{length}个字
+        /// </summary>
+        /// <param name="s"></param>
+        /// <param name="length"></param>
+        /// <returns></returns>
+        public static string Take(this string s, int length)
+        {
+            return s.Length > length ? s.Substring(0, length) : s;
+        }
+
+        /// <summary>
+        /// 对比字符串的汉明距离
+        /// </summary>
+        /// <param name="this"></param>
+        /// <param name="that"></param>
+        /// <returns></returns>
+        public static int HammingDistance(this string @this, string that) => new SimHash(@this).HammingDistance(new SimHash(that));
+
+        /// <summary>
+        /// 匹配字符串是否包含emoji字符
+        /// </summary>
+        /// <param name="s"></param>
+        /// <returns></returns>
+        public static bool MatchEmoji(this string s)
+        {
+            return Regex.IsMatch(s, @"(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])");
+        }
+
+        /// <summary>
+        /// 获取字符串的字符数
+        /// </summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        public static int CharacterCount(this string str)
+        {
+            var enumerator = StringInfo.GetTextElementEnumerator(str);
+            int length = 0;
+            while (enumerator.MoveNext())
+            {
+                length++;
+            }
+
+            return length;
+        }
+
+        /// <summary>
+        /// 获取字符串的字节数
+        /// </summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        public static int BytesCount(this string str)
+        {
+            return Encoding.UTF8.GetByteCount(str);
+        }
+
+        /// <summary>
+        /// 转半角(DBC case)
+        /// </summary>
+        /// <param name="input">任意字符串</param>
+        /// <returns>半角字符串</returns>
+        ///<remarks>
+        ///全角空格为12288,半角空格为32(此处不必转空格)
+        ///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
+        ///</remarks>
+        public static string ToDBC(this string input)
+        {
+            char[] c = input.ToCharArray();
+            for (int i = 0; i < c.Length; i++)
+            {
+                if (c[i] == 12288)
+                {
+                    c[i] = (char)32;
+                    continue;
+                }
+
+                if (c[i] > 65280 && c[i] < 65375)
+                {
+                    c[i] = (char)(c[i] - 65248);
+                }
+            }
+
+            return new string(c);
+        }
+
+        /// <summary>
+        /// 转全角(SBC case)
+        /// </summary>
+        /// <param name="input">任意字符串</param>
+        /// <returns>全角字符串</returns>
+        ///<remarks>
+        ///全角空格为12288,半角空格为32
+        ///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
+        ///</remarks>
+        public static string ToSBC(this string input)
+        {
+            //半角转全角:
+            var c = input.ToCharArray();
+            for (int i = 0; i < c.Length; i++)
+            {
+                if (c[i] == 32)
+                {
+                    c[i] = (char)12288;
+                    continue;
+                }
+                if (c[i] < 127 && c[i] > 32)
+                {
+                    c[i] = (char)(c[i] + 65248);
+                }
+            }
+            return new string(c);
+        }
+    }
 }

+ 166 - 167
Masuit.Tools.Abstractions/Extensions/BaseType/ValueTypeConvertExtensions.cs

@@ -1,192 +1,191 @@
 using System;
 using Masuit.Tools.Strings;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class ValueTypeConvertExtensions
 {
-    public static class ValueTypeConvertExtensions
-    {
-        /// <summary>
-        /// 字符串转int
-        /// </summary>
-        /// <param name="s">源字符串</param>
-        /// <param name="defaultValue">转换失败的默认值</param>
-        /// <returns>int类型的数字</returns>
-        public static int ToInt32(this string s, int defaultValue = 0)
-        {
-            return s.TryConvertTo(defaultValue);
-        }
+    /// <summary>
+    /// 字符串转int
+    /// </summary>
+    /// <param name="s">源字符串</param>
+    /// <param name="defaultValue">转换失败的默认值</param>
+    /// <returns>int类型的数字</returns>
+    public static int ToInt32(this string s, int defaultValue = 0)
+    {
+        return s.TryConvertTo(defaultValue);
+    }
 
-        /// <summary>
-        /// 字符串转long
-        /// </summary>
-        /// <param name="s">源字符串</param>
-        /// <param name="defaultValue">转换失败的默认值</param>
-        /// <returns>int类型的数字</returns>
-        public static long ToInt64(this string s, long defaultValue = 0)
-        {
-            return s.TryConvertTo(defaultValue);
-        }
+    /// <summary>
+    /// 字符串转long
+    /// </summary>
+    /// <param name="s">源字符串</param>
+    /// <param name="defaultValue">转换失败的默认值</param>
+    /// <returns>int类型的数字</returns>
+    public static long ToInt64(this string s, long defaultValue = 0)
+    {
+        return s.TryConvertTo(defaultValue);
+    }
 
-        /// <summary>
-        /// 字符串转double
-        /// </summary>
-        /// <param name="s">源字符串</param>
-        /// <param name="defaultValue">转换失败的默认值</param>
-        /// <returns>double类型的数据</returns>
-        public static double ToDouble(this string s, double defaultValue = 0)
-        {
-            return s.TryConvertTo(defaultValue);
-        }
+    /// <summary>
+    /// 字符串转double
+    /// </summary>
+    /// <param name="s">源字符串</param>
+    /// <param name="defaultValue">转换失败的默认值</param>
+    /// <returns>double类型的数据</returns>
+    public static double ToDouble(this string s, double defaultValue = 0)
+    {
+        return s.TryConvertTo(defaultValue);
+    }
 
-        /// <summary>
-        /// 字符串转decimal
-        /// </summary>
-        /// <param name="s">源字符串</param>
-        /// <param name="defaultValue">转换失败的默认值</param>
-        /// <returns>int类型的数字</returns>
-        public static decimal ToDecimal(this string s, decimal defaultValue = 0)
-        {
-            return s.TryConvertTo(defaultValue);
-        }
+    /// <summary>
+    /// 字符串转decimal
+    /// </summary>
+    /// <param name="s">源字符串</param>
+    /// <param name="defaultValue">转换失败的默认值</param>
+    /// <returns>int类型的数字</returns>
+    public static decimal ToDecimal(this string s, decimal defaultValue = 0)
+    {
+        return s.TryConvertTo(defaultValue);
+    }
 
-        /// <summary>
-        /// 字符串转decimal
-        /// </summary>
-        /// <param name="s">源字符串</param>
-        /// <param name="round">小数位数</param>
-        /// <param name="defaultValue">转换失败的默认值</param>
-        /// <returns>int类型的数字</returns>
-        public static decimal ToDecimal(this string s, int round, decimal defaultValue = 0)
-        {
-            return Math.Round(s.TryConvertTo(defaultValue), round, MidpointRounding.AwayFromZero);
-        }
+    /// <summary>
+    /// 字符串转decimal
+    /// </summary>
+    /// <param name="s">源字符串</param>
+    /// <param name="round">小数位数</param>
+    /// <param name="defaultValue">转换失败的默认值</param>
+    /// <returns>int类型的数字</returns>
+    public static decimal ToDecimal(this string s, int round, decimal defaultValue = 0)
+    {
+        return Math.Round(s.TryConvertTo(defaultValue), round, MidpointRounding.AwayFromZero);
+    }
 
-        /// <summary>
-        /// 转double
-        /// </summary>
-        /// <param name="num"></param>
-        /// <returns>double类型的数据</returns>
-        public static double ToDouble(this decimal num)
-        {
-            return (double)num;
-        }
+    /// <summary>
+    /// 转double
+    /// </summary>
+    /// <param name="num"></param>
+    /// <returns>double类型的数据</returns>
+    public static double ToDouble(this decimal num)
+    {
+        return (double)num;
+    }
 
-        /// <summary>
-        /// 将double转换成int
-        /// </summary>
-        /// <param name="num">double类型</param>
-        /// <returns>int类型</returns>
-        public static int ToInt32(this double num)
-        {
-            return (int)Math.Floor(num);
-        }
+    /// <summary>
+    /// 将double转换成int
+    /// </summary>
+    /// <param name="num">double类型</param>
+    /// <returns>int类型</returns>
+    public static int ToInt32(this double num)
+    {
+        return (int)Math.Floor(num);
+    }
 
-        /// <summary>
-        /// 将double转换成int
-        /// </summary>
-        /// <param name="num">double类型</param>
-        /// <returns>int类型</returns>
-        public static int ToInt32(this decimal num)
-        {
-            return (int)Math.Floor(num);
-        }
+    /// <summary>
+    /// 将double转换成int
+    /// </summary>
+    /// <param name="num">double类型</param>
+    /// <returns>int类型</returns>
+    public static int ToInt32(this decimal num)
+    {
+        return (int)Math.Floor(num);
+    }
 
-        /// <summary>
-        /// 将int转换成double
-        /// </summary>
-        /// <param name="num">int类型</param>
-        /// <returns>int类型</returns>
-        public static double ToDouble(this int num)
-        {
-            return num * 1.0;
-        }
+    /// <summary>
+    /// 将int转换成double
+    /// </summary>
+    /// <param name="num">int类型</param>
+    /// <returns>int类型</returns>
+    public static double ToDouble(this int num)
+    {
+        return num * 1.0;
+    }
 
-        /// <summary>
-        /// 将int转换成decimal
-        /// </summary>
-        /// <param name="num">int类型</param>
-        /// <returns>int类型</returns>
-        public static decimal ToDecimal(this int num)
-        {
-            return new decimal(num);
-        }
+    /// <summary>
+    /// 将int转换成decimal
+    /// </summary>
+    /// <param name="num">int类型</param>
+    /// <returns>int类型</returns>
+    public static decimal ToDecimal(this int num)
+    {
+        return new decimal(num);
+    }
 
-        /// <summary>
-        /// 保留小数
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="decimals"></param>
-        /// <param name="mode">四舍五入策略</param>
-        /// <returns></returns>
-        public static decimal Round(this decimal num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
-        {
-            num = Math.Round(num, decimals, mode);
-            return num;
-        }
+    /// <summary>
+    /// 保留小数
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="decimals"></param>
+    /// <param name="mode">四舍五入策略</param>
+    /// <returns></returns>
+    public static decimal Round(this decimal num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    {
+        num = Math.Round(num, decimals, mode);
+        return num;
+    }
 
-        /// <summary>
-        /// 保留小数
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="decimals"></param>
-        /// <param name="mode">四舍五入策略</param>
-        /// <returns></returns>
-        public static double Round(this double num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
-        {
-            num = Math.Round(num, decimals, mode);
-            return num;
-        }
+    /// <summary>
+    /// 保留小数
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="decimals"></param>
+    /// <param name="mode">四舍五入策略</param>
+    /// <returns></returns>
+    public static double Round(this double num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    {
+        num = Math.Round(num, decimals, mode);
+        return num;
+    }
 
-        /// <summary>
-        /// 保留小数
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="decimals"></param>
-        /// <param name="mode">四舍五入策略</param>
-        /// <returns></returns>
-        public static decimal? Round(this decimal? num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    /// <summary>
+    /// 保留小数
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="decimals"></param>
+    /// <param name="mode">四舍五入策略</param>
+    /// <returns></returns>
+    public static decimal? Round(this decimal? num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    {
+        if (num.HasValue)
         {
-            if (num.HasValue)
-            {
-                num = Math.Round(num.Value, decimals, mode);
-            }
-            return num;
+            num = Math.Round(num.Value, decimals, mode);
         }
+        return num;
+    }
 
-        /// <summary>
-        /// 保留小数
-        /// </summary>
-        /// <param name="num"></param>
-        /// <param name="decimals"></param>
-        /// <param name="mode">四舍五入策略</param>
-        /// <returns></returns>
-        public static double? Round(this double? num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    /// <summary>
+    /// 保留小数
+    /// </summary>
+    /// <param name="num"></param>
+    /// <param name="decimals"></param>
+    /// <param name="mode">四舍五入策略</param>
+    /// <returns></returns>
+    public static double? Round(this double? num, int decimals, MidpointRounding mode = MidpointRounding.AwayFromZero)
+    {
+        if (num.HasValue)
         {
-            if (num.HasValue)
-            {
-                num = Math.Round(num.Value, decimals, mode);
-            }
-            return num;
+            num = Math.Round(num.Value, decimals, mode);
         }
+        return num;
+    }
 
-        /// <summary>
-        /// 转换为中文数字格式
-        /// </summary>
-        /// <param name="number"></param>
-        /// <returns></returns>
-        public static string ToChineseNumber(this IConvertible number)
-        {
-            return NumberFormater.ToChineseNumber(number);
-        }
+    /// <summary>
+    /// 转换为中文数字格式
+    /// </summary>
+    /// <param name="number"></param>
+    /// <returns></returns>
+    public static string ToChineseNumber(this IConvertible number)
+    {
+        return NumberFormater.ToChineseNumber(number);
+    }
 
-        /// <summary>
-        /// 数字转中文金额大写
-        /// </summary>
-        /// <param name="number"></param>
-        /// <returns></returns>
-        public static string ToChineseMoney(this IConvertible number)
-        {
-            return NumberFormater.ToChineseMoney(number);
-        }
+    /// <summary>
+    /// 数字转中文金额大写
+    /// </summary>
+    /// <param name="number"></param>
+    /// <returns></returns>
+    public static string ToChineseMoney(this IConvertible number)
+    {
+        return NumberFormater.ToChineseMoney(number);
     }
 }

+ 22 - 25
Masuit.Tools.Abstractions/Extensions/Dynamics/Behaviors/ArrayBehavior.cs

@@ -7,7 +7,7 @@ namespace Masuit.Tools.Dynamics.Behaviors;
 
 internal class ArrayBehavior : ClayBehavior
 {
-    private readonly List<object> _data = new();
+    private readonly List<object> _data = [];
 
     /// <inheritdoc />
     public override object GetIndex(Func<object> proceed, object self, IEnumerable<string> keys)
@@ -33,6 +33,7 @@ internal class ArrayBehavior : ClayBehavior
             case "GetEnumerator":
                 return new Clay(new InterfaceProxyBehavior(), new EnumeratorBehavior(_data.GetEnumerator()));
         }
+
         return proceed();
     }
 
@@ -50,9 +51,17 @@ internal class ArrayBehavior : ClayBehavior
                 return self;
 
             case "Insert":
-                return IfInitialInteger(args, (index, arr) => { _data.InsertRange(index, arr); return self; }, proceed);
+                return IfInitialInteger(args, (index, arr) =>
+                {
+                    _data.InsertRange(index, arr);
+                    return self;
+                }, proceed);
             case "RemoveAt":
-                return IfSingleInteger(args, index => { _data.RemoveAt(index); return self; }, proceed);
+                return IfSingleInteger(args, index =>
+                {
+                    _data.RemoveAt(index);
+                    return self;
+                }, proceed);
             case "Contains":
                 return IfSingleArgument(args, arg => _data.Contains(arg), proceed);
 
@@ -70,12 +79,7 @@ internal class ArrayBehavior : ClayBehavior
                 }, proceed);
         }
 
-        if (!args.Any())
-        {
-            return GetMember(proceed, self, name);
-        }
-
-        return proceed();
+        return args.Any() ? proceed() : GetMember(proceed, self, name);
     }
 
     private static object IfArguments<T1, T2>(IEnumerable<object> args, Func<T1, T2, object> func, Func<object> proceed)
@@ -108,45 +112,38 @@ internal class ArrayBehavior : ClayBehavior
         return proceed();
     }
 
-    private class EnumeratorBehavior : ClayBehavior
+    private class EnumeratorBehavior(IEnumerator enumerator) : ClayBehavior
     {
-        private readonly IEnumerator _enumerator;
-
-        public EnumeratorBehavior(IEnumerator enumerator)
-        {
-            _enumerator = enumerator;
-        }
-
         public override object InvokeMember(Func<object> proceed, object self, string name, INamedEnumerable<object> args)
         {
             switch (name)
             {
                 case "MoveNext":
-                    return _enumerator.MoveNext();
+                    return enumerator.MoveNext();
 
                 case "Reset":
-                    _enumerator.Reset();
+                    enumerator.Reset();
                     return null;
 
                 case "Dispose":
-                    if (_enumerator is IDisposable disposable)
+                    if (enumerator is IDisposable disposable)
                     {
                         disposable.Dispose();
                     }
 
                     return null;
             }
+
             return proceed();
         }
 
         public override object GetMember(Func<object> proceed, object self, string name)
         {
-            switch (name)
+            return name switch
             {
-                case "Current":
-                    return _enumerator.Current;
-            }
-            return proceed();
+                "Current" => enumerator.Current,
+                _ => proceed()
+            };
         }
     }
 }

+ 2 - 9
Masuit.Tools.Abstractions/Extensions/Dynamics/Behaviors/InterfaceProxyBehavior.cs

@@ -36,21 +36,14 @@ internal class InterfaceProxyBehavior : ClayBehavior
         return Activator.CreateInstance(proxyType, interceptors, self);
     }
 
-    private class Interceptor : IInterceptor
+    private class Interceptor(object self) : IInterceptor
     {
-        private object Self { get; }
-
-        public Interceptor(object self)
-        {
-            Self = self;
-        }
-
         public void Intercept(IInvocation invocation)
         {
             if (invocation.Method == DynamicMetaObjectProviderGetMetaObject)
             {
                 var expression = (Expression)invocation.Arguments.Single();
-                invocation.ReturnValue = new ForwardingMetaObject(expression, BindingRestrictions.Empty, invocation.Proxy, (IDynamicMetaObjectProvider)Self, exprProxy => Expression.Field(exprProxy, "__target"));
+                invocation.ReturnValue = new ForwardingMetaObject(expression, BindingRestrictions.Empty, invocation.Proxy, (IDynamicMetaObjectProvider)self, exprProxy => Expression.Field(exprProxy, "__target"));
                 return;
             }
 

+ 5 - 9
Masuit.Tools.Abstractions/Extensions/Dynamics/Behaviors/NullBehavior.cs

@@ -39,15 +39,11 @@ internal class NullBehavior : ClayBehavior
     /// <inheritdoc />
     public override object BinaryOperation(Func<object> proceed, object self, ExpressionType operation, object value)
     {
-        switch (operation)
+        return operation switch
         {
-            case ExpressionType.Equal:
-                return ReferenceEquals(value, NullInstance.Instance) || value == null;
-
-            case ExpressionType.NotEqual:
-                return !ReferenceEquals(value, NullInstance.Instance) && value != null;
-        }
-
-        return proceed();
+            ExpressionType.Equal => ReferenceEquals(value, NullInstance.Instance) || value == null,
+            ExpressionType.NotEqual => !ReferenceEquals(value, NullInstance.Instance) && value != null,
+            _ => proceed()
+        };
     }
 }

+ 52 - 57
Masuit.Tools.Abstractions/Extensions/Dynamics/Clay.cs

@@ -7,71 +7,66 @@ using Masuit.Tools.Dynamics.Implementation;
 
 namespace Masuit.Tools.Dynamics;
 
-public class Clay : IDynamicMetaObjectProvider, IClayBehaviorProvider
+public class Clay(IEnumerable<IClayBehavior> behaviors) : IDynamicMetaObjectProvider, IClayBehaviorProvider
 {
-	private readonly ClayBehaviorCollection _behavior;
+    private readonly ClayBehaviorCollection _behavior = new(behaviors);
 
-	public Clay() : this(Enumerable.Empty<IClayBehavior>())
-	{
-	}
+    public Clay() : this(Enumerable.Empty<IClayBehavior>())
+    {
+    }
 
-	public Clay(params IClayBehavior[] behaviors) : this(behaviors.AsEnumerable())
-	{
-	}
+    public Clay(params IClayBehavior[] behaviors) : this(behaviors.AsEnumerable())
+    {
+    }
 
-	public Clay(IEnumerable<IClayBehavior> behaviors)
-	{
-		_behavior = new ClayBehaviorCollection(behaviors);
-	}
+    DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
+    {
+        return new ClayMetaObject(this, parameter);
+    }
 
-	DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
-	{
-		return new ClayMetaObject(this, parameter);
-	}
+    IClayBehavior IClayBehaviorProvider.Behavior => _behavior;
 
-	IClayBehavior IClayBehaviorProvider.Behavior => _behavior;
+    /// <inheritdoc />
+    public override string ToString()
+    {
+        var fallback = base.ToString();
+        return _behavior.InvokeMember(() => fallback, this, "ToString", Arguments.Empty()) as string ?? string.Empty;
+    }
 
-	/// <inheritdoc />
-	public override string ToString()
-	{
-		var fallback = base.ToString();
-		return _behavior.InvokeMember(() => fallback, this, "ToString", Arguments.Empty()) as string ?? string.Empty;
-	}
+    public Dictionary<string, object> ToDictionary()
+    {
+        return _behavior.OfType<PropBehavior>().FirstOrDefault()?.GetProps();
+    }
 
-	public Dictionary<string, object> ToDictionary()
-	{
-		return _behavior.OfType<PropBehavior>().FirstOrDefault()?.GetProps();
-	}
+    /// <summary>
+    /// 移除属性
+    /// </summary>
+    /// <param name="left"></param>
+    /// <param name="right"></param>
+    public static Clay operator -(Clay left, string right)
+    {
+        left.ToDictionary().Remove(right);
+        return left;
+    }
 
-	/// <summary>
-	/// 移除属性
-	/// </summary>
-	/// <param name="left"></param>
-	/// <param name="right"></param>
-	public static Clay operator -(Clay left, string right)
-	{
-		left.ToDictionary().Remove(right);
-		return left;
-	}
+    /// <summary>
+    /// 移除属性
+    /// </summary>
+    /// <param name="left"></param>
+    /// <param name="right"></param>
+    public static Clay operator +(Clay left, string right)
+    {
+        left[right] = DynamicFactory.NewObject();
+        return left;
+    }
 
-	/// <summary>
-	/// 移除属性
-	/// </summary>
-	/// <param name="left"></param>
-	/// <param name="right"></param>
-	public static Clay operator +(Clay left, string right)
-	{
-		left[right] = DynamicFactory.NewObject();
-		return left;
-	}
-
-	/// <summary>
-	///
-	/// </summary>
-	/// <param name="key"></param>
-	public object this[string key]
-	{
-		get => ToDictionary()[key];
-		set => ToDictionary()[key] = value;
-	}
+    /// <summary>
+    ///
+    /// </summary>
+    /// <param name="key"></param>
+    public object this[string key]
+    {
+        get => ToDictionary()[key];
+        set => ToDictionary()[key] = value;
+    }
 }

+ 1 - 6
Masuit.Tools.Abstractions/Extensions/Dynamics/ClayBehaviorCollection.cs

@@ -5,13 +5,8 @@ using System.Linq.Expressions;
 
 namespace Masuit.Tools.Dynamics;
 
-internal class ClayBehaviorCollection : List<IClayBehavior>, IClayBehavior
+internal class ClayBehaviorCollection(IEnumerable<IClayBehavior> behaviors) : List<IClayBehavior>(behaviors), IClayBehavior
 {
-    public ClayBehaviorCollection(IEnumerable<IClayBehavior> behaviors)
-        : base(behaviors)
-    {
-    }
-
     private object Execute(Func<object> proceed, Func<Func<object>, IClayBehavior, Func<object>> linker)
     {
         return this.Aggregate(proceed, linker)();

+ 1 - 6
Masuit.Tools.Abstractions/Extensions/Dynamics/ClayMetaObject.cs

@@ -8,10 +8,9 @@ using Masuit.Tools.Dynamics.Implementation;
 
 namespace Masuit.Tools.Dynamics;
 
-internal class ClayMetaObject : DynamicMetaObject
+internal class ClayMetaObject(object value, Expression expression) : DynamicMetaObject(expression, BindingRestrictions.Empty, value)
 {
     private static readonly MethodInfo ClayBehaviorInvokeMember = typeof(IClayBehavior).GetMethod("InvokeMember");
-
     private static readonly MethodInfo ClayBehaviorGetMember = typeof(IClayBehavior).GetMethod("GetMember");
     private static readonly MethodInfo ClayBehaviorSetMember = typeof(IClayBehavior).GetMethod("SetMember");
     private static readonly MethodInfo ClayBehaviorGetIndex = typeof(IClayBehavior).GetMethod("GetIndex");
@@ -23,10 +22,6 @@ internal class ClayMetaObject : DynamicMetaObject
     private static readonly MethodInfo ClayBehaviorSetMemberMissing = typeof(IClayBehavior).GetMethod("SetMemberMissing");
     private static readonly MethodInfo ClayBehaviorConvertMissing = typeof(IClayBehavior).GetMethod("ConvertMissing");
 
-    public ClayMetaObject(object value, Expression expression) : base(expression, BindingRestrictions.Empty, value)
-    {
-    }
-
     public ClayMetaObject(object value, Expression expression, Func<Expression, Expression> getClayBehavior) : this(value, expression)
     {
         _getClayBehavior = getClayBehavior;

+ 4 - 11
Masuit.Tools.Abstractions/Extensions/Dynamics/DefaultClayActivator.cs

@@ -8,7 +8,7 @@ namespace Masuit.Tools.Dynamics;
 
 internal class DefaultClayActivator : IClayActivator
 {
-    private static readonly IProxyBuilder _builder = new DefaultProxyBuilder();
+    private static readonly IProxyBuilder Builder = new DefaultProxyBuilder();
 
     public dynamic CreateInstance(Type baseType, IEnumerable<IClayBehavior> behaviors, IEnumerable<object> arguments)
     {
@@ -46,7 +46,7 @@ internal class DefaultClayActivator : IClayActivator
             };
         }
 
-        var proxyType = _builder.CreateClassProxyType(baseType, Type.EmptyTypes, options);
+        var proxyType = Builder.CreateClassProxyType(baseType, Type.EmptyTypes, options);
         constructorArgs.Add(new IInterceptor[]
         {
             new ClayInterceptor()
@@ -59,16 +59,9 @@ internal class DefaultClayActivator : IClayActivator
         return contextualize(Activator.CreateInstance(proxyType, constructorArgs.ToArray()));
     }
 
-    private class MixinClayBehaviorProvider : IClayBehaviorProvider
+    private class MixinClayBehaviorProvider(IEnumerable<IClayBehavior> behaviors) : IClayBehaviorProvider
     {
-        private readonly IClayBehavior _behavior;
-
-        public MixinClayBehaviorProvider(IEnumerable<IClayBehavior> behaviors)
-        {
-            _behavior = new ClayBehaviorCollection(behaviors);
-        }
-
-        IClayBehavior IClayBehaviorProvider.Behavior => _behavior;
+        IClayBehavior IClayBehaviorProvider.Behavior { get; } = new ClayBehaviorCollection(behaviors);
     }
 
     private class MixinDynamicMetaObjectProvider : IDynamicMetaObjectProvider

+ 7 - 21
Masuit.Tools.Abstractions/Extensions/Dynamics/Implementation/Arguments.cs

@@ -69,8 +69,10 @@ internal static class Arguments
 
             public Named(IEnumerable<T> arguments, IEnumerable<string> names)
             {
-                _arguments = arguments.Skip(arguments.Count() - names.Count());
-                _names = names;
+                var args = arguments as IList<T> ?? arguments.ToList();
+                var ns = names as IList<string> ?? names.ToList();
+                _arguments = args.Skip(args.Count - ns.Count());
+                _names = ns;
             }
 
             private IEnumerable<KeyValuePair<string, T>> MakeEnumerable()
@@ -141,29 +143,13 @@ internal static class Arguments
 
             T IDictionary<string, T>.this[string key]
             {
-                get
-                {
-                    return MakeEnumerable().Where(kv => kv.Key == key).Select(kv => kv.Value).FirstOrDefault();
-                }
-
+                get => MakeEnumerable().Where(kv => kv.Key == key).Select(kv => kv.Value).FirstOrDefault();
                 set => throw new NotImplementedException();
             }
 
-            ICollection<string> IDictionary<string, T>.Keys
-            {
-                get
-                {
-                    return _namesCollection ??= _names as ICollection<string> ?? _names.ToArray();
-                }
-            }
+            ICollection<string> IDictionary<string, T>.Keys => _namesCollection ??= _names as ICollection<string> ?? _names.ToArray();
 
-            ICollection<T> IDictionary<string, T>.Values
-            {
-                get
-                {
-                    return _argumentsCollection ??= _arguments as ICollection<T> ?? _arguments.ToArray();
-                }
-            }
+            ICollection<T> IDictionary<string, T>.Values => _argumentsCollection ??= _arguments as ICollection<T> ?? _arguments.ToArray();
         }
     }
 

File diff ditekan karena terlalu besar
+ 218 - 314
Masuit.Tools.Abstractions/Files/FileDetector/AbstractCompoundFileDetailDetector.cs


+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/AbstractFullRegexDetector.cs

@@ -43,7 +43,7 @@ public abstract class AbstractFullRegexDetector : IDetector
         foreach (var encoding in encodings)
         {
             stream.Position = 0;
-            using var reader = new StreamReader(stream, encoding, true, 4096, true);
+            var reader = new StreamReader(stream, encoding, true, 4096, true);
             string buffer = reader.ReadToEnd();
             if (Pattern.Replace(buffer, "") == string.Empty)
             {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/AbstractISOBaseMediaFileDetailDetector.cs

@@ -21,7 +21,7 @@ public abstract class AbstractISOBaseMediaFileDetailDetector : IDetector
 
     public virtual bool Detect(Stream stream)
     {
-        using var reader = new BinaryReader(stream, Encoding.UTF8, true);
+        var reader = new BinaryReader(stream, Encoding.UTF8, true);
         int offset = reader.ReadInt32();
 
         if (reader.ReadByte() == 0x66 && reader.ReadByte() == 0x74 && reader.ReadByte() == 0x79 && reader.ReadByte() == 0x70)

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/AbstractRegexSignatureDetector.cs

@@ -36,7 +36,7 @@ public abstract class AbstractRegexSignatureDetector : IDetector
         foreach (var encoding in encodings)
         {
             stream.Position = 0;
-            using StreamReader reader = new StreamReader(stream, encoding, true, readBufferSize, true);
+            var reader = new StreamReader(stream, encoding, true, readBufferSize, true);
             reader.ReadBlock(buffer, 0, readBufferSize);
             if (Signature.IsMatch(new string(buffer)))
             {

+ 2 - 11
Masuit.Tools.Abstractions/Files/FileDetector/AbstractZipDetailDetector.cs

@@ -28,17 +28,8 @@ public abstract class AbstractZipDetailDetector : IDetector
     {
         try
         {
-            using var archive = new ZipArchive(stream, ZipArchiveMode.Read, true);
-            foreach (string filename in Files)
-            {
-                bool succeed = archive.Entries.Any(entry => entry.FullName == filename && IsValid(filename, entry));
-                if (!succeed)
-                {
-                    return false;
-                }
-            }
-
-            return true;
+            var archive = new ZipArchive(stream, ZipArchiveMode.Read, true);
+            return Files.Select(filename => archive.Entries.Any(entry => entry.FullName == filename && IsValid(filename, entry))).All(succeed => succeed);
         }
         catch
         {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ApkDetector.cs

@@ -8,7 +8,7 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 [FormatCategory(FormatCategory.Archive)]
 [FormatCategory(FormatCategory.Compression)]
 [FormatCategory(FormatCategory.Executable)]
-internal class ApkDetector : AbstractZipDetailDetector
+internal sealed class ApkDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 3 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/AudioVideoInterleaveDetector.cs

@@ -7,11 +7,11 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Video)]
 [FormatCategory(FormatCategory.Audio)]
-internal class AudioVideoInterleaveDetector : AbstractSignatureDetector
+internal sealed class AudioVideoInterleaveDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] AviSignatureInfo = {
-        new () { Position = 0, Signature = new byte [] { 0x52, 0x49, 0x46, 0x46 } },
-        new () { Position = 8, Signature = new byte [] { 0x41, 0x56, 0x49, 0x20 }, Presignature = new byte [] { 0x52, 0x49, 0x46, 0x46 } },
+        new () { Position = 0, Signature = "RIFF"u8.ToArray() },
+        new () { Position = 8, Signature = "AVI "u8.ToArray(), Presignature = "RIFF"u8.ToArray() },
     };
 
     public override string Extension => "avi";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/BashShellScriptDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Executable)]
-internal class BashShellScriptDetector : AbstractRegexSignatureDetector
+internal sealed class BashShellScriptDetector : AbstractRegexSignatureDetector
 {
     public override string Precondition => "txt";
 

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/BinaryPropertyListDetector.cs

@@ -6,10 +6,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class BinaryPropertyListDetector : AbstractSignatureDetector
+internal sealed class BinaryPropertyListDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] BplistSignatureInfo = {
-        new () { Position = 0, Signature = new byte [] { 0x62, 0x70, 0x6C, 0x69, 0x73, 0x74 } },
+        new () { Position = 0, Signature = "bplist"u8.ToArray() },
     };
 
     public override string Extension => "bplist";

+ 3 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/BitmapDetector.cs

@@ -6,11 +6,11 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class BitmapDetector : AbstractSignatureDetector
+internal sealed class BitmapDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] BmpSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x42, 0x4D } },
-        new() { Position = 6, Signature = new byte [] { 0x00, 0x00, 0x00, 0x00 }, Presignature = new byte [] { 0x42, 0x4D } },
+        new() { Position = 0, Signature = "BM"u8.ToArray() },
+        new() { Position = 6, Signature = new byte [] { 0x00, 0x00, 0x00, 0x00 }, Presignature = "BM"u8.ToArray() },
     };
 
     public override string Extension => "bmp";

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/Bzip2Detector.cs

@@ -6,10 +6,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Compression)]
-internal class Bzip2Detector : AbstractSignatureDetector
+internal sealed class Bzip2Detector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] Bz2SignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x42, 0x5A, 0x68 } },
+        new() { Position = 0, Signature = "BZh"u8.ToArray() },
     };
 
     public override string Extension => "bz2";

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CabDetector.cs

@@ -6,10 +6,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class CabDetector : AbstractSignatureDetector
+internal sealed class CabDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] CabSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x4D, 0x53, 0x43, 0x46 } },
+        new() { Position = 0, Signature = "MSCF"u8.ToArray() },
     };
 
     public override string Extension => "cab";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CertDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class CertDetector : AbstractSignatureDetector
+internal sealed class CertDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] CrtSignatureInfo = {
         new() { Position = 0, Signature = Encoding.GetEncoding ( "ascii" ).GetBytes ( "-----BEGIN CERTIFICATE-----" ) },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CompoundHWPDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class CompoundHWPDetector : AbstractCompoundFileDetailDetector
+internal sealed class CompoundHWPDetector : AbstractCompoundFileDetailDetector
 {
     public override IEnumerable<string> Chunks
     {

+ 3 - 9
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ConfigurationDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class ConfigurationDetector : IDetector
+internal sealed class ConfigurationDetector : IDetector
 {
     public string Precondition => "txt";
 
@@ -25,15 +25,9 @@ internal class ConfigurationDetector : IDetector
             var reader = XmlReader.Create(stream, new XmlReaderSettings()
             {
             });
-            if (reader.Read())
+            if (reader.Read() && reader.IsStartElement() && reader.Name == "configuration")
             {
-                if (reader.IsStartElement())
-                {
-                    if (reader.Name == "configuration")
-                    {
-                        return true;
-                    }
-                }
+                return true;
             }
         }
         catch

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/CursorDetector.cs

@@ -6,7 +6,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class CursorDetector : AbstractSignatureDetector
+internal sealed class CursorDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] CurSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x00, 0x00, 0x02, 0x00 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DLLDetector.cs

@@ -9,7 +9,7 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.System)]
 [FormatCategory(FormatCategory.Executable)]
-internal class DLLDetector : IDetector
+internal sealed class DLLDetector : IDetector
 {
     public string Precondition => "exe";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DMGDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class DMGDetector : AbstractSignatureDetector
+internal sealed class DMGDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] DmgSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x78, 0x01, 0x73, 0x0D, 0x62, 0x62, 0x60 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DOCXDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class DOCXDetector : AbstractZipDetailDetector
+internal sealed class DOCXDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/DirectDrawSurfaceFormatDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class DirectDrawSurfaceFormatDetector : AbstractSignatureDetector
+internal sealed class DirectDrawSurfaceFormatDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] DdsSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x44, 0x44, 0x53, 0x20 } },
+        new() { Position = 0, Signature = "DDS "u8.ToArray() },
     };
 
     public override string Extension => "dds";

+ 3 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/EXEDetector.cs

@@ -8,10 +8,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Executable)]
-internal class EXEDetector : AbstractSignatureDetector
+internal sealed class EXEDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] ExeSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x4D, 0x5A } },
+        new() { Position = 0, Signature = "MZ"u8.ToArray() },
     };
 
     public override string Extension => "exe";
@@ -27,7 +27,7 @@ internal class EXEDetector : AbstractSignatureDetector
         if (base.Detect(stream))
         {
             stream.Position = 60;
-            using BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true);
+            var reader = new BinaryReader(stream, Encoding.UTF8, true);
             stream.Position = reader.ReadInt32();
             return reader.ReadByte() == 0x50 && reader.ReadByte() == 0x45 && reader.ReadByte() == 0 && reader.ReadByte() == 0;
         }

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/EpubDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class EpubDetector : AbstractZipDetailDetector
+internal sealed class EpubDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {
@@ -31,7 +31,7 @@ internal class EpubDetector : AbstractZipDetailDetector
     {
         if (filename == "mimetype")
         {
-            using Stream mimetypeStream = entry.Open();
+            var mimetypeStream = entry.Open();
             byte[] buffer = new byte["application/epub+zip".Length];
             if (mimetypeStream.Read(buffer, 0, buffer.Length) != buffer.Length)
             {

+ 4 - 4
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/FLVDetector.cs

@@ -7,15 +7,15 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Video)]
-internal class FLVDetector : AbstractSignatureDetector
+internal sealed class FLVDetector : AbstractSignatureDetector
 {
-    private static SignatureInformation[] FLV_SignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x46, 0x4C, 0x56 } },
+    private static readonly SignatureInformation[] FlvSignatureInfo = {
+        new() { Position = 0, Signature = "FLV"u8.ToArray() },
     };
 
     public override string Extension => "flv";
 
-    protected override SignatureInformation[] SignatureInformations => FLV_SignatureInfo;
+    protected override SignatureInformation[] SignatureInformations => FlvSignatureInfo;
 
     public override string MimeType => new MimeMapper().GetMimeFromExtension("." + Extension);
 

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/FlacDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Audio)]
-internal class FlacDetector : AbstractSignatureDetector
+internal sealed class FlacDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] FlacSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x66, 0x4C, 0x61, 0x43 } },
+        new() { Position = 0, Signature = "fLaC"u8.ToArray() },
     };
 
     public override string Extension => "flac";

+ 3 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/GifDetector.cs

@@ -8,11 +8,11 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Video)]
 [FormatCategory(FormatCategory.Image)]
-internal class GifDetector : AbstractSignatureDetector
+internal sealed class GifDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] GifSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 } },
-        new() { Position = 0, Signature = new byte [] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 } },
+        new() { Position = 0, Signature = "GIF87a"u8.ToArray() },
+        new() { Position = 0, Signature = "GIF89a"u8.ToArray() },
     };
 
     public override string Extension => "gif";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/GzDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Compression)]
-internal class GzDetector : AbstractSignatureDetector
+internal sealed class GzDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] GzSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x1F, 0x8B } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/HWPDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class HWPDetector : AbstractRegexSignatureDetector
+internal sealed class HWPDetector : AbstractRegexSignatureDetector
 {
     public override string Extension => "hwp";
 

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ISODetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class ISODetector : AbstractSignatureDetector
+internal sealed class ISODetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] IsoSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x43, 0x44, 0x30, 0x30, 0x31 } },
+        new() { Position = 0, Signature = "CD001"u8.ToArray() },
     };
 
     public override string Extension => "iso";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/IconDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class IconDetector : AbstractSignatureDetector
+internal sealed class IconDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] IcoSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x00, 0x00, 0x01, 0x00 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/InitializationDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class InitializationDetector : AbstractRegexSignatureDetector
+internal sealed class InitializationDetector : AbstractRegexSignatureDetector
 {
     public override string Precondition => "txt";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/JavaClassDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Executable)]
-internal class JavaClassDetector : AbstractSignatureDetector
+internal sealed class JavaClassDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] ClassSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0xCA, 0xFE, 0xBA, 0xBE } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/Jpeg2000Detector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class Jpeg2000Detector : AbstractSignatureDetector
+internal sealed class Jpeg2000Detector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] JpegSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/JpegDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class JpegDetector : AbstractSignatureDetector
+internal sealed class JpegDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] JpegSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0xFF, 0xD8, 0xFF, 0xFE, 0x00 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/JpegXRDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class JpegXRDetector : AbstractSignatureDetector
+internal sealed class JpegXRDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] JpegSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x49, 0x49, 0xBC, 0x01 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/KTXDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class KTXDetector : AbstractSignatureDetector
+internal sealed class KTXDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] KtxSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A } },

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/LzhDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Compression)]
-internal class LzhDetector : AbstractSignatureDetector
+internal sealed class LzhDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] LzhSignatureInfo = {
-        new() { Position = 2, Signature = new byte [] { 0x2D, 0x6C, 0x68 } },
+        new() { Position = 2, Signature = "-lh"u8.ToArray() },
     };
 
     public override string Extension => "lzh";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/M4ADetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Audio)]
-internal class M4ADetector : AbstractISOBaseMediaFileDetailDetector
+internal sealed class M4ADetector : AbstractISOBaseMediaFileDetailDetector
 {
     public override string Extension => "m4a";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/M4VDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Video)]
-internal class M4VDetector : AbstractISOBaseMediaFileDetailDetector
+internal sealed class M4VDetector : AbstractISOBaseMediaFileDetailDetector
 {
     public override string Extension => "m4v";
 

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MP3Detector.cs

@@ -7,11 +7,11 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Audio)]
-internal class MP3Detector : AbstractSignatureDetector
+internal sealed class MP3Detector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] Mp3SignatureInfo = {
         new () { Position = 0, Signature = new byte [] { 0xFF, 0xFB } },
-        new () { Position = 0, Signature = new byte [] { 0x49, 0x44, 0x33 } },
+        new () { Position = 0, Signature = "ID3"u8.ToArray() },
     };
 
     public override string Extension => "mp3";

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MP4Detector.cs

@@ -9,7 +9,7 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 [FormatCategory(FormatCategory.Video)]
 [FormatCategory(FormatCategory.Audio)]
 [FormatCategory(FormatCategory.Image)]
-internal class MP4Detector : AbstractISOBaseMediaFileDetailDetector
+internal sealed class MP4Detector : AbstractISOBaseMediaFileDetailDetector
 {
     public override string Extension => "mp4";
 
@@ -26,4 +26,4 @@ internal class MP4Detector : AbstractISOBaseMediaFileDetailDetector
     public override List<FormatCategory> FormatCategories => GetType().GetCustomAttributes<FormatCategoryAttribute>().Select(a => a.Category).ToList();
 
     public override string ToString() => "MP4 Detector";
-}
+}

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftExcelXLSDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class MicrosoftExcelXLSDetector : AbstractCompoundFileDetailDetector
+internal sealed class MicrosoftExcelXLSDetector : AbstractCompoundFileDetailDetector
 {
     public override IEnumerable<string> Chunks
     {

+ 4 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftInstallerDetector.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Reflection;
@@ -8,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class MicrosoftInstallerDetector : AbstractCompoundFileDetailDetector
+internal sealed class MicrosoftInstallerDetector : AbstractCompoundFileDetailDetector
 {
     public override IEnumerable<string> Chunks
     {
@@ -26,7 +27,7 @@ internal class MicrosoftInstallerDetector : AbstractCompoundFileDetailDetector
 
     protected override bool IsValidChunk(string chunkName, byte[] chunkData)
     {
-        return chunkName == "SummaryInformation" && Encoding.ASCII.GetString(chunkData, 0, chunkData.Length).IndexOf("Installation Database") != -1;
+        return chunkName == "SummaryInformation" && Encoding.ASCII.GetString(chunkData, 0, chunkData.Length).IndexOf("Installation Database", StringComparison.Ordinal) != -1;
     }
 
     public override string ToString() => "Microsoft Installer Setup File Detector";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftPowerPointPPTDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class MicrosoftPowerPointPPTDetector : AbstractCompoundFileDetailDetector
+internal sealed class MicrosoftPowerPointPPTDetector : AbstractCompoundFileDetailDetector
 {
     public override IEnumerable<string> Chunks
     {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MicrosoftWordDocDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class MicrosoftWordDocDetector : AbstractCompoundFileDetailDetector
+internal sealed class MicrosoftWordDocDetector : AbstractCompoundFileDetailDetector
 {
     public override IEnumerable<string> Chunks
     {

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MidiDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Audio)]
-internal class MidiDetector : AbstractSignatureDetector
+internal sealed class MidiDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] MidiSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x4D, 0x54, 0x68, 0x64 } },
+        new() { Position = 0, Signature = "MThd"u8.ToArray() },
     };
 
     public override string Extension => "mid";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/MikeOBrienPackDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class MikeOBrienPackDetector : AbstractSignatureDetector
+internal sealed class MikeOBrienPackDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] MpqSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x4D, 0x50, 0x51, 0x1A } },

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OggDetector.cs

@@ -8,10 +8,10 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Audio)]
 [FormatCategory(FormatCategory.Video)]
-internal class OggDetector : AbstractSignatureDetector
+internal sealed class OggDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] OggSignatureInfo = {
-        new () { Position = 0, Signature = new byte [] { 0x4F, 0x67, 0x67, 0x53 } },
+        new () { Position = 0, Signature = "OggS"u8.ToArray() },
     };
 
     public override string Extension => "ogg";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentFormulaDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class OpenDocumentFormulaDetector : AbstractZipDetailDetector
+internal sealed class OpenDocumentFormulaDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentGraphicsDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class OpenDocumentGraphicsDetector : AbstractZipDetailDetector
+internal sealed class OpenDocumentGraphicsDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentPresentationDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class OpenDocumentPresentationDetector : AbstractZipDetailDetector
+internal sealed class OpenDocumentPresentationDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 3 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentSpreadSheetDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class OpenDocumentSpreadSheetDetector : AbstractZipDetailDetector
+internal sealed class OpenDocumentSpreadSheetDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {
@@ -31,8 +31,8 @@ internal class OpenDocumentSpreadSheetDetector : AbstractZipDetailDetector
     {
         if (filename == "mimetype")
         {
-            using Stream mimetypeStream = entry.Open();
-            byte[] buffer = new byte["application/vnd.oasis.opendocument.spreadsheet".Length];
+            var mimetypeStream = entry.Open();
+            var buffer = new byte["application/vnd.oasis.opendocument.spreadsheet".Length];
             if (mimetypeStream.Read(buffer, 0, buffer.Length) != buffer.Length)
             {
                 return false;

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/OpenDocumentTextDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class OpenDocumentTextDetector : AbstractZipDetailDetector
+internal sealed class OpenDocumentTextDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PAKArchiveDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class PAKArchiveDetector : AbstractSignatureDetector
+internal sealed class PAKArchiveDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] PakSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x1A, 0x0B } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PDBDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class PDBDetector : AbstractRegexSignatureDetector
+internal sealed class PDBDetector : AbstractRegexSignatureDetector
 {
     public override string Extension => "pdb";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PFXDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class PFXDetector : AbstractSignatureDetector
+internal sealed class PFXDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] PfxSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x30, 0x82, 0x06 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PKMDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class PKMDetector : AbstractSignatureDetector
+internal sealed class PKMDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] PkmSignatureInfo = {
         new() { Position = 0, Signature = Encoding.ASCII.GetBytes ( "PKM 10" ) },

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PPSXDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class PPSXDetector : AbstractZipDetailDetector
+internal sealed class PPSXDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {
@@ -32,7 +32,7 @@ internal class PPSXDetector : AbstractZipDetailDetector
     {
         if (filename == "[Content_Types].xml")
         {
-            using StreamReader reader = new StreamReader(entry.Open());
+            var reader = new StreamReader(entry.Open());
             var text = reader.ReadToEnd();
             return text.IndexOf("<Override PartName=\"/ppt/presentation.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml\"/>") >= 0;
         }

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PPTXDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class PPTXDetector : AbstractZipDetailDetector
+internal sealed class PPTXDetector : AbstractZipDetailDetector
 {
     public override IEnumerable<string> Files
     {

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PdfDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class PdfDetector : AbstractRegexSignatureDetector
+internal sealed class PdfDetector : AbstractRegexSignatureDetector
 {
     public override string Extension => "pdf";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PngDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class PngDetector : AbstractSignatureDetector
+internal sealed class PngDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] PngSignatureInfo = {
         new () { Position = 0, Signature = new byte [] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PrePOSIXtarDetector.cs

@@ -9,7 +9,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class POSIXtarDetector : IDetector
+internal sealed class POSIXtarDetector : IDetector
 {
     public string Precondition => null;
 

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/PsdDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class PsdDetector : AbstractSignatureDetector
+internal sealed class PsdDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] PsdSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x38, 0x42, 0x50, 0x53 } },
+        new() { Position = 0, Signature = "8BPS"u8.ToArray() },
     };
 
     public override string Extension => "psd";

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/QuakeArchiveDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class QuakeArchiveDetector : AbstractSignatureDetector
+internal sealed class QuakeArchiveDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] PakSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x50, 0x41, 0x43, 0x4B } },
+        new() { Position = 0, Signature = "PACK"u8.ToArray() },
     };
 
     public override string Extension => "pak";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/QuickTimeDetector.cs

@@ -8,7 +8,7 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Video)]
 [FormatCategory(FormatCategory.Audio)]
-internal class QuickTimeDetector : AbstractISOBaseMediaFileDetailDetector
+internal sealed class QuickTimeDetector : AbstractISOBaseMediaFileDetailDetector
 {
     public override string Extension => "mov";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/REGDetector.cs

@@ -9,7 +9,7 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
 [FormatCategory(FormatCategory.System)]
-internal class REGDetector : AbstractRegexSignatureDetector
+internal sealed class REGDetector : AbstractRegexSignatureDetector
 {
     public override string Precondition => "txt";
 

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/RarDetector.cs

@@ -8,7 +8,7 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
 [FormatCategory(FormatCategory.Compression)]
-internal class RarDetector : AbstractSignatureDetector
+internal sealed class RarDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] RarSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/RedhatPackageManagerPackageDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class RedhatPackageManagerPackageDetector : AbstractSignatureDetector
+internal sealed class RedhatPackageManagerPackageDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] RpmSignatureInfo = {
         new() { Position = 0, Signature = new byte [] { 0xED, 0xAB, 0xEE, 0xDB } },

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/RichTextFormatDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class RichTextFormatDetector : AbstractSignatureDetector
+internal sealed class RichTextFormatDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] RtfSignatureInfo = {
-        new () { Position = 0, Signature = new byte [] { 0x7B, 0x5C, 0x72, 0x74, 0x66, 0x31 } },
+        new () { Position = 0, Signature = "{\\rtf1"u8.ToArray() },
     };
 
     public override string Extension => "rtf";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/SQLiteDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class SQLiteDetector : AbstractSignatureDetector
+internal sealed class SQLiteDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] SqliteSignatureInfo = {
         new () { Position = 0, Signature = new byte [] { 0x53, 0x51, 0x4C, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x20, 0x33, 0x00 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/SRTDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class SRTDetector : AbstractRegexSignatureDetector
+internal sealed class SRTDetector : AbstractRegexSignatureDetector
 {
     public override string Precondition => "txt";
 

+ 3 - 3
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ShockwaveFlashDetector.cs

@@ -8,11 +8,11 @@ namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Video)]
 [FormatCategory(FormatCategory.Executable)]
-internal class ShockwaveFlashDetector : AbstractSignatureDetector
+internal sealed class ShockwaveFlashDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] SwfSignatureInfo = {
-        new() { Position = 0, Signature = new byte [] { 0x43, 0x57, 0x53 } },
-        new() { Position = 0, Signature = new byte [] { 0x46, 0x57, 0x53 } },
+        new() { Position = 0, Signature = "CWS"u8.ToArray() },
+        new() { Position = 0, Signature = "FWS"u8.ToArray() },
     };
 
     public override string Extension => "swf";

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/TextDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class TextDetector : IDetector
+internal sealed class TextDetector : IDetector
 {
     private static readonly byte[] SignatureBuffer = new byte[4];
     private static readonly char[] TextBuffer = new char[4096];

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/TgaDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class TgaDetector : IDetector
+internal sealed class TgaDetector : IDetector
 {
     public string Extension => "tga";
 
@@ -28,7 +28,7 @@ internal class TgaDetector : IDetector
 
         stream.Position = 17;
         int depth = stream.ReadByte();
-        if (!(depth == 8 || depth == 24 || depth == 15 || depth == 16 || depth == 32))
+        if (depth is not (8 or 24 or 15 or 16 or 32))
         {
             return false;
         }

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/ThumbsDBDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.System)]
-internal class ThumbsDBDetector : AbstractSignatureDetector
+internal sealed class ThumbsDBDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] ThumbdbSignatureInfo = {
         new () { Position = 0, Signature = new byte [] { 0xFD, 0xFF, 0xFF, 0xFF } },

+ 2 - 2
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/TiffDetector.cs

@@ -7,10 +7,10 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Image)]
-internal class TiffDetector : AbstractSignatureDetector
+internal sealed class TiffDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] TiffSignatureInfo = {
-        new () { Position = 0, Signature = new byte [] { 0x49, 0x49, 0x49 } },
+        new () { Position = 0, Signature = "III"u8.ToArray() },
         new () { Position = 0, Signature = new byte [] { 0x49, 0x49, 0x2A, 0x00 } },
         new () { Position = 0, Signature = new byte [] { 0x4D, 0x4D, 0x00, 0x2A } },
         new () { Position = 0, Signature = new byte [] { 0x4D, 0x4D, 0x00, 0x2B } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/UStarFormatTarDetector.cs

@@ -7,7 +7,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Archive)]
-internal class UStarFormatTarDetector : AbstractSignatureDetector
+internal sealed class UStarFormatTarDetector : AbstractSignatureDetector
 {
     private static readonly SignatureInformation[] TarSignatureInfo = {
         new () { Position = 0x101, Signature = new byte [] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 } },

+ 1 - 1
Masuit.Tools.Abstractions/Files/FileDetector/Detectors/VisualStudioSolutionDetector.cs

@@ -8,7 +8,7 @@ using Masuit.Tools.Mime;
 namespace Masuit.Tools.Files.FileDetector.Detectors;
 
 [FormatCategory(FormatCategory.Document)]
-internal class VisualStudioSolutionDetector : AbstractRegexSignatureDetector
+internal sealed class VisualStudioSolutionDetector : AbstractRegexSignatureDetector
 {
     public override string Precondition => "txt";
 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini