浏览代码

1. 增加DistributedCache扩展
2. 值类型转换优化
3. 树形结构转换优化

懒得勤快 3 年之前
父节点
当前提交
3f6811bc14

+ 176 - 73
Masuit.Tools.Abstractions/Extensions/BaseType/IConvertibleExtensions.cs

@@ -1,108 +1,211 @@
 using System;
+using System.ComponentModel;
 using System.Globalization;
 
-namespace Masuit.Tools
+namespace Masuit.Tools;
+
+public static class IConvertibleExtensions
 {
-    public static class IConvertibleExtensions
+    public static bool IsNumeric(this Type type)
     {
-        /// <summary>
-        /// 类型直转
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="value"></param>
-        /// <returns></returns>
-
-        public static T ConvertTo<T>(this IConvertible value) where T : IConvertible
+        switch (Type.GetTypeCode(type))
         {
-            return (T)ConvertTo(value, typeof(T));
+            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>
-        /// <param name="defaultValue">转换失败的默认值</param>
-        /// <returns></returns>
-        public static T TryConvertTo<T>(this IConvertible value, T defaultValue = default) where T : IConvertible
+    /// <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)
         {
-            try
+            var type = typeof(T);
+            if (value.GetType() == type)
             {
-                return (T)ConvertTo(value, typeof(T));
+                return (T)value;
             }
-            catch
+
+            if (type.IsNumeric())
             {
-                return defaultValue;
+                return (T)value.ToType(type, new NumberFormatInfo());
             }
-        }
 
-        /// <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
+            if (value == DBNull.Value)
             {
-                result = (T)ConvertTo(value, typeof(T));
-                return true;
+                return default;
             }
-            catch
+
+            if (type.IsEnum)
             {
-                result = default;
-                return false;
+                return (T)Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
             }
-        }
 
-        /// <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
+            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
             {
-                result = ConvertTo(value, type);
-                return true;
+                var underlyingType = Nullable.GetUnderlyingType(type);
+                return (T)(underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType));
             }
-            catch
+
+            TypeConverter converter = TypeDescriptor.GetConverter(value);
+            if (converter != null)
             {
-                result = default;
-                return false;
+                if (converter.CanConvertTo(type))
+                {
+                    return (T)converter.ConvertTo(value, type);
+                }
             }
-        }
 
-        /// <summary>
-        /// 类型直转
-        /// </summary>
-        /// <param name="value"></param>
-        /// <param name="type">目标类型</param>
-        /// <returns></returns>
-        public static object ConvertTo(this IConvertible value, Type type)
-        {
-            if (null == value)
+            converter = TypeDescriptor.GetConverter(type);
+            if (converter != null)
             {
-                return default;
+                if (converter.CanConvertFrom(value.GetType()))
+                {
+                    return (T)converter.ConvertFrom(value);
+                }
             }
+            return (T)Convert.ChangeType(value, type);
+        }
 
-            if (type.IsEnum)
+        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.IsNumeric())
+        {
+            return value.ToType(type, new NumberFormatInfo());
+        }
+
+        if (type.IsEnum)
+        {
+            return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
+        }
+
+        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 != null)
+        {
+            if (converter.CanConvertTo(type))
             {
-                return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
+                return converter.ConvertTo(value, type);
             }
+        }
 
-            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
+        converter = TypeDescriptor.GetConverter(type);
+        if (converter != null)
+        {
+            if (converter.CanConvertFrom(value.GetType()))
             {
-                var underlyingType = Nullable.GetUnderlyingType(type);
-                return underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType);
+                return converter.ConvertFrom(value);
             }
-
-            return Convert.ChangeType(value, type);
         }
+
+        return value;
     }
 }

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

@@ -3,7 +3,7 @@
         <TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5;net6</TargetFrameworks>
         <LangVersion>latest</LangVersion>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-        <Version>2.5.3-beta</Version>
+        <Version>2.5.3</Version>
         <Authors>懒得勤快</Authors>
         <Description>Masuit.Tools基础公共库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。</Description>
         <Copyright>懒得勤快,长空X</Copyright>

+ 34 - 43
Masuit.Tools.Abstractions/Models/TreeExtensions.cs

@@ -19,17 +19,15 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<T> Filter<T>(this IEnumerable<T> items, Func<T, bool> func) where T : class, ITreeChildren<T>
         {
-            var results = new List<T>();
             foreach (var item in items.Where(i => i != null))
             {
                 item.Children ??= new List<T>();
                 item.Children = item.Children.Filter(func).ToList();
                 if (item.Children.Any() || func(item))
                 {
-                    results.Add(item);
+                    yield return item;
                 }
             }
-            return results;
         }
 
         /// <summary>
@@ -41,18 +39,15 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<Tree<T>> Filter<T>(this IEnumerable<Tree<T>> items, Func<Tree<T>, bool> func) where T : class
         {
-            var results = new List<Tree<T>>();
             foreach (var item in items.Where(i => i != null))
             {
                 item.Children ??= new List<Tree<T>>();
                 item.Children = item.Children.Filter(func).ToList();
                 if (item.Children.Any() || func(item))
                 {
-                    results.Add(item);
+                    yield return item;
                 }
             }
-
-            return results;
         }
 
         /// <summary>
@@ -88,16 +83,16 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items, Action<T, T> optionAction = null) where T : class, ITreeChildren<T>
         {
-            var result = new List<T>();
             foreach (var item in items)
             {
-                result.Add(item);
+                yield return item;
                 item.Children ??= new List<T>();
                 item.Children.ForEach(c => optionAction?.Invoke(c, item));
-                result.AddRange(item.Children.Flatten(optionAction));
+                foreach (var children in item.Children.Flatten(optionAction))
+                {
+                    yield return children;
+                }
             }
-
-            return result;
         }
 
         /// <summary>
@@ -109,19 +104,17 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<T> Flatten<T>(this T p, Action<T, T> optionAction = null) where T : class, ITreeChildren<T>
         {
-            var result = new List<T>()
-            {
-                p
-            };
+            yield return p;
             foreach (var item in p.Children)
             {
-                result.Add(item);
+                yield return item;
                 item.Children ??= new List<T>();
                 item.Children.ForEach(c => optionAction?.Invoke(c, item));
-                result.AddRange(item.Children.Flatten());
+                foreach (var children in item.Children.Flatten())
+                {
+                    yield return children;
+                }
             }
-
-            return result;
         }
 
         /// <summary>
@@ -134,15 +127,15 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector, Action<T, T> optionAction = null)
         {
-            var result = new List<T>();
             foreach (var item in items)
             {
-                result.Add(item);
+                yield return item;
                 selector(item).ForEach(c => optionAction?.Invoke(c, item));
-                result.AddRange(selector(item).Flatten(selector));
+                foreach (var children in selector(item).Flatten(selector))
+                {
+                    yield return children;
+                }
             }
-
-            return result;
         }
 
         /// <summary>
@@ -154,16 +147,16 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<Tree<T>> Flatten<T>(this IEnumerable<Tree<T>> items, Action<Tree<T>, Tree<T>> optionAction = null) where T : class
         {
-            var result = new List<Tree<T>>();
             foreach (var item in items)
             {
-                result.Add(item);
+                yield return item;
                 item.Children ??= new List<Tree<T>>();
                 item.Children.ForEach(c => optionAction?.Invoke(c, item));
-                result.AddRange(item.Children.Flatten());
+                foreach (var tree in item.Children.Flatten())
+                {
+                    yield return tree;
+                }
             }
-
-            return result;
         }
 
         /// <summary>
@@ -175,19 +168,17 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<Tree<T>> Flatten<T>(this Tree<T> p, Action<Tree<T>, Tree<T>> optionAction = null) where T : class
         {
-            var result = new List<Tree<T>>()
-            {
-                p
-            };
+            yield return p;
             foreach (var item in p.Children)
             {
-                result.Add(item);
+                yield return item;
                 item.Children ??= new List<Tree<T>>();
                 item.Children.ForEach(c => optionAction?.Invoke(c, item));
-                result.AddRange(item.Children.Flatten());
+                foreach (var tree in item.Children.Flatten())
+                {
+                    yield return tree;
+                }
             }
-
-            return result;
         }
 
         /// <summary>
@@ -200,15 +191,15 @@ namespace Masuit.Tools.Models
         /// <returns></returns>
         public static IEnumerable<Tree<T>> Flatten<T>(this IEnumerable<Tree<T>> items, Func<Tree<T>, IEnumerable<Tree<T>>> selector, Action<Tree<T>, Tree<T>> optionAction = null)
         {
-            var result = new List<Tree<T>>();
             foreach (var item in items)
             {
-                result.Add(item);
+                yield return item;
                 item.Children.ForEach(c => optionAction?.Invoke(c, item));
-                result.AddRange(selector(item).Flatten(selector));
+                foreach (var tree in selector(item).Flatten(selector))
+                {
+                    yield return tree;
+                }
             }
-
-            return result;
         }
 
         /// <summary>

+ 75 - 0
Masuit.Tools.AspNetCore/Extensions/DistributedCacheExt.cs

@@ -0,0 +1,75 @@
+using System;
+using System.Text;
+using Masuit.Tools.Systems;
+using Microsoft.Extensions.Caching.Distributed;
+using Newtonsoft.Json;
+
+namespace Masuit.Tools.AspNetCore.Extensions;
+
+/// <summary>
+/// 
+/// </summary>
+public static class DistributedCacheExt
+{
+    public static T GetOrAdd<T>(this IDistributedCache cache, string key, Func<T> valueFactory)
+    {
+        var bytes = cache.Get(key);
+        if (bytes is null)
+        {
+            var value = new NullObject<T>(valueFactory());
+            bytes = Encoding.UTF8.GetBytes(value.ToJsonString());
+            cache.Set(key, bytes);
+            return value;
+        }
+
+        return JsonConvert.DeserializeObject<NullObject<T>>(Encoding.UTF8.GetString(bytes));
+    }
+
+    public static T Get<T>(this IDistributedCache cache, string key)
+    {
+        var bytes = cache.Get(key);
+        if (bytes is null)
+        {
+            return default;
+        }
+
+        return JsonConvert.DeserializeObject<NullObject<T>>(Encoding.UTF8.GetString(bytes));
+    }
+
+    public static void Set<T>(this IDistributedCache cache, string key, T value)
+    {
+        cache.Set(key, Encoding.UTF8.GetBytes(new NullObject<T>(value).ToJsonString()), new DistributedCacheEntryOptions());
+    }
+
+    public static void Set<T>(this IDistributedCache cache, string key, T value, DistributedCacheEntryOptions options)
+    {
+        cache.Set(key, Encoding.UTF8.GetBytes(new NullObject<T>(value).ToJsonString()), options);
+    }
+
+    public static T GetOrAdd<T>(this IDistributedCache cache, string key, T value)
+    {
+        var bytes = cache.Get(key);
+        if (bytes is null)
+        {
+            bytes = Encoding.UTF8.GetBytes(new NullObject<T>(value).ToJsonString());
+            cache.Set(key, bytes);
+            return value;
+        }
+
+        return JsonConvert.DeserializeObject<NullObject<T>>(Encoding.UTF8.GetString(bytes));
+    }
+
+    public static void AddOrUpdate<T>(this IDistributedCache cache, string key, T addValue, Func<T, T> updateFunc)
+    {
+        var bytes = cache.Get(key);
+        if (bytes is null)
+        {
+            bytes = Encoding.UTF8.GetBytes(new NullObject<T>(addValue).ToJsonString());
+            cache.Set(key, bytes);
+            return;
+        }
+
+        var value = new NullObject<T>(updateFunc(JsonConvert.DeserializeObject<NullObject<T>>(Encoding.UTF8.GetString(bytes))));
+        cache.Set(key, Encoding.UTF8.GetBytes(value.ToJsonString()));
+    }
+}

+ 3 - 3
Masuit.Tools.AspNetCore/Extensions/ViewDataDictionaryExt.cs

@@ -1,5 +1,5 @@
-using System;
-using Microsoft.AspNetCore.Mvc.ViewFeatures;
+using Microsoft.AspNetCore.Mvc.ViewFeatures;
+using System;
 
 namespace Masuit.Tools.AspNetCore.Extensions;
 
@@ -19,4 +19,4 @@ public static class ViewDataDictionaryExt
     {
         return (T)(dic[s] ?? defaultValue());
     }
-}
+}

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

@@ -18,7 +18,7 @@
         <LangVersion>latest</LangVersion>
         <RepositoryType>Github</RepositoryType>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-        <Version>1.1.3-beta</Version>
+        <Version>1.1.3</Version>
         <FileVersion>1.0</FileVersion>
         <Company>masuit.com</Company>
         <AssemblyVersion>1.0</AssemblyVersion>

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

@@ -19,7 +19,7 @@ github:https://github.com/ldqk/Masuit.Tools
         <UserSecretsId>830c282f-f7c1-42be-8651-4cd06ac8e73f</UserSecretsId>
         <RepositoryType>Github</RepositoryType>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-        <Version>2.5.3-beta</Version>
+        <Version>2.5.3</Version>
         <FileVersion>2.4.5.6</FileVersion>
         <Company>masuit.com</Company>
         <AssemblyVersion>2.4.5.6</AssemblyVersion>

+ 1 - 1
Masuit.Tools.Net45/package.nuspec

@@ -2,7 +2,7 @@
 <package>
   <metadata>
     <id>Masuit.Tools.Net45</id>
-    <version>2.5.3-beta</version>
+    <version>2.5.3</version>
     <title>Masuit.Tools</title>
     <authors>懒得勤快</authors>
     <owners>masuit.com</owners>

+ 1 - 1
Masuit.Tools/package.nuspec

@@ -2,7 +2,7 @@
 <package>
   <metadata>
     <id>Masuit.Tools.Net</id>
-    <version>2.5.3-beta</version>
+    <version>2.5.3</version>
     <title>Masuit.Tools</title>
     <authors>懒得勤快</authors>
     <owners>masuit.com</owners>