Explorar o código

DbSet类型支持递归Include
Newtonsoft支持自定义忽略行为

懒得勤快 %!s(int64=3) %!d(string=hai) anos
pai
achega
53907daf9c

+ 1 - 1
Masuit.Tools.Abstractions/Linq/LinqExtension.cs

@@ -57,4 +57,4 @@ namespace Masuit.Tools.Linq
             return Sub.TryGetValue(node, out var newValue) ? newValue : node;
         }
     }
-}
+}

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

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

+ 18 - 1
Masuit.Tools.Abstractions/Models/TreeExtensions.cs

@@ -470,12 +470,29 @@ namespace Masuit.Tools.Models
         /// </summary>
         public static string Path<T>(this T tree, Func<T, string> selector) where T : ITreeParent<T> => GetFullPath(tree, selector);
 
+        /// <summary>
+        /// 节点路径
+        /// </summary>
+        /// <param name="tree"></param>
+        /// <param name="separator">分隔符</param>
+        public static string Path<T>(this T tree, string separator) where T : ITree<T> => GetFullPath(tree, t => t.Name, separator);
+
+        /// <summary>
+        /// 节点路径
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="tree"></param>
+        /// <param name="selector">选择字段</param>
+        /// <param name="separator">分隔符</param>
+        /// <returns></returns>
+        public static string Path<T>(this T tree, Func<T, string> selector, string separator) where T : ITreeParent<T> => GetFullPath(tree, selector, separator);
+
         /// <summary>
         /// 根节点
         /// </summary>
         public static T Root<T>(this T tree) where T : ITreeParent<T> => GetRoot(tree, t => t.Parent);
 
-        private static string GetFullPath<T>(T c, Func<T, string> selector) where T : ITreeParent<T> => c.Parent != null ? GetFullPath(c.Parent, selector) + "/" + selector(c) : selector(c);
+        private static string GetFullPath<T>(T c, Func<T, string> selector, string separator = "/") where T : ITreeParent<T> => c.Parent != null ? GetFullPath(c.Parent, selector) + separator + selector(c) : selector(c);
 
         /// <summary>
         /// 根节点

+ 6 - 2
Masuit.Tools.Abstractions/Systems/CompositeContractResolver.cs

@@ -15,11 +15,15 @@ public class CompositeContractResolver : FallbackJsonPropertyResolver
         var property = base.CreateProperty(member, memberSerialization);
         if (property is { Writable: true })
         {
-            var attributes = property.AttributeProvider.GetAttributes(typeof(DeserializeOnlyJsonPropertyAttribute), true).Union(property.AttributeProvider.GetAttributes(typeof(SerializeIgnoreAttribute), true));
-            if (attributes.Any())
+            if (property.AttributeProvider.GetAttributes(typeof(DeserializeOnlyJsonPropertyAttribute), true).Union(property.AttributeProvider.GetAttributes(typeof(SerializeIgnoreAttribute), true)).Any())
             {
                 property.ShouldSerialize = _ => false;
             }
+
+            if (property.AttributeProvider.GetAttributes(typeof(SerializeOnlyJsonPropertyAttribute), true).Union(property.AttributeProvider.GetAttributes(typeof(DeserializeIgnoreAttribute), true)).Any())
+            {
+                property.ShouldDeserialize = _ => false;
+            }
         }
 
         return property;

+ 6 - 2
Masuit.Tools.Abstractions/Systems/DeserializeOnlyContractResolver.cs

@@ -15,11 +15,15 @@ public class DeserializeOnlyContractResolver : DefaultContractResolver
         var property = base.CreateProperty(member, memberSerialization);
         if (property is { Writable: true })
         {
-            var attributes = property.AttributeProvider.GetAttributes(typeof(DeserializeOnlyJsonPropertyAttribute), true).Union(property.AttributeProvider.GetAttributes(typeof(SerializeIgnoreAttribute), true));
-            if (attributes.Any())
+            if (property.AttributeProvider.GetAttributes(typeof(DeserializeOnlyJsonPropertyAttribute), true).Union(property.AttributeProvider.GetAttributes(typeof(SerializeIgnoreAttribute), true)).Any())
             {
                 property.ShouldSerialize = _ => false;
             }
+
+            if (property.AttributeProvider.GetAttributes(typeof(SerializeOnlyJsonPropertyAttribute), true).Union(property.AttributeProvider.GetAttributes(typeof(DeserializeIgnoreAttribute), true)).Any())
+            {
+                property.ShouldDeserialize = _ => false;
+            }
         }
 
         return property;

+ 8 - 0
Masuit.Tools.Abstractions/Systems/DeserializeOnlyJsonPropertyAttribute.cs

@@ -9,3 +9,11 @@ namespace Masuit.Tools.Systems;
 public class DeserializeOnlyJsonPropertyAttribute : Attribute
 {
 }
+
+/// <summary>
+/// 只允许反序列化
+/// </summary>
+[AttributeUsage(AttributeTargets.Property)]
+public class SerializeOnlyJsonPropertyAttribute : Attribute
+{
+}

+ 81 - 0
Masuit.Tools.Abstractions/Systems/FallbackJsonPropertyResolver.cs

@@ -12,6 +12,86 @@ namespace Masuit.Tools.Systems;
 /// </summary>
 public class FallbackJsonPropertyResolver : CamelCasePropertyNamesContractResolver
 {
+    /// <summary>
+    /// 序列化时忽略的字段集
+    /// </summary>
+    protected readonly Dictionary<Type, HashSet<string>> SerializeIgnores = new();
+
+    /// <summary>
+    /// 反序列化时忽略的字段集
+    /// </summary>
+    protected readonly Dictionary<Type, HashSet<string>> DeserializeIgnores = new();
+
+    /// <summary>
+    /// 序列化时忽略
+    /// </summary>
+    /// <param name="type">类型</param>
+    /// <param name="propertyName">属性名</param>
+    /// <returns></returns>
+    public FallbackJsonPropertyResolver SerializeIgnore(Type type, params string[] propertyName)
+    {
+        if (!SerializeIgnores.ContainsKey(type)) SerializeIgnores[type] = new HashSet<string>();
+        foreach (var prop in propertyName)
+        {
+            SerializeIgnores[type].Add(prop);
+        }
+
+        return this;
+    }
+
+    /// <summary>
+    /// 反序列化时忽略
+    /// </summary>
+    /// <param name="type">类型</param>
+    /// <param name="propertyName">属性名</param>
+    /// <returns></returns>
+    public FallbackJsonPropertyResolver DeserializeIgnore(Type type, params string[] propertyName)
+    {
+        if (!DeserializeIgnores.ContainsKey(type)) DeserializeIgnores[type] = new HashSet<string>();
+        foreach (var prop in propertyName)
+        {
+            DeserializeIgnores[type].Add(prop);
+        }
+
+        return this;
+    }
+
+    public bool IsSerializeIgnored(Type type, string propertyName)
+    {
+        if (!SerializeIgnores.ContainsKey(type)) return false;
+        if (SerializeIgnores[type].Count == 0) return true;
+        return SerializeIgnores[type].Contains(propertyName, StringComparer.CurrentCultureIgnoreCase);
+    }
+
+    public bool IsDeserializeIgnored(Type type, string propertyName)
+    {
+        if (!DeserializeIgnores.ContainsKey(type)) return false;
+        if (DeserializeIgnores[type].Count == 0) return true;
+        return DeserializeIgnores[type].Contains(propertyName, StringComparer.CurrentCultureIgnoreCase);
+    }
+
+    /// <summary>
+    /// The decision logic goes here
+    /// </summary>
+    /// <param name="member"></param>
+    /// <param name="memberSerialization"></param>
+    /// <returns></returns>
+    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
+    {
+        var property = base.CreateProperty(member, memberSerialization);
+        if (IsSerializeIgnored(property.DeclaringType, property.PropertyName))
+        {
+            property.ShouldSerialize = _ => false;
+        }
+
+        if (IsDeserializeIgnored(property.DeclaringType, property.PropertyName))
+        {
+            property.ShouldDeserialize = _ => false;
+        }
+
+        return property;
+    }
+
     protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
     {
         var typeMembers = GetSerializableMembers(type).DistinctBy(m => m.Name);
@@ -33,6 +113,7 @@ public class FallbackJsonPropertyResolver : CamelCasePropertyNamesContractResolv
 
             foreach (var alternateName in fallbackAttribute.FallbackReadNames)
             {
+                properties.RemoveAll(p => p.PropertyName == alternateName);
                 var fallbackProperty = CreateProperty(member, memberSerialization);
                 fallbackProperty.PropertyName = alternateName;
                 fallbackProperty.ShouldSerialize = (x) => false;

+ 9 - 1
Masuit.Tools.Abstractions/Systems/SerializeIgnoreAttribute.cs

@@ -8,4 +8,12 @@ namespace Masuit.Tools.Systems;
 [AttributeUsage(AttributeTargets.Property)]
 public class SerializeIgnoreAttribute : Attribute
 {
-}
+}
+
+/// <summary>
+/// 序列化时忽略
+/// </summary>
+[AttributeUsage(AttributeTargets.Property)]
+public class DeserializeIgnoreAttribute : Attribute
+{
+}

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

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

+ 20 - 1
Masuit.Tools.Core/Database/DbContextExt.cs

@@ -3,7 +3,9 @@ using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
+using System.Linq.Expressions;
 using System.Reflection;
+using System.Text;
 
 namespace Masuit.Tools.Core
 {
@@ -192,6 +194,23 @@ namespace Masuit.Tools.Core
         {
             return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db));
         }
+
+        public static IQueryable<TEntity> IncludeRecursive<TEntity>(this IQueryable<TEntity> source,
+          int levelIndex, Expression<Func<TEntity, ICollection<TEntity>>> expression) where TEntity : class
+        {
+            if (levelIndex < 0)
+                throw new ArgumentOutOfRangeException(nameof(levelIndex));
+            var member = (MemberExpression)expression.Body;
+            var property = member.Member.Name;
+            var sb = new StringBuilder();
+            for (int i = 0; i < levelIndex; i++)
+            {
+                if (i > 0)
+                    sb.Append(Type.Delimiter);
+                sb.Append(property);
+            }
+            return source.Include(sb.ToString());
+        }
     }
 
     public class ChangePropertyInfo
@@ -244,4 +263,4 @@ namespace Masuit.Tools.Core
         /// </summary>
         public List<ChangePropertyInfo> ChangeProperties { get; set; }
     }
-}
+}

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

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