From dee8f22055c70620694cbf5ca8a926c4d20b7161 Mon Sep 17 00:00:00 2001 From: maliming Date: Sun, 1 Nov 2020 23:13:56 +0800 Subject: [PATCH] Enhanced SystemTextJsonSupportTypeMatcher. --- .../SystemTextJsonSupportTypeMatcher.cs | 130 +++++++++++++++++- .../SystemTextJsonSupportTypeMatcher_Tests.cs | 30 ++++ 2 files changed, 153 insertions(+), 7 deletions(-) diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypeMatcher.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypeMatcher.cs index 440d453c37..9ac2f16f78 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypeMatcher.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypeMatcher.cs @@ -10,7 +10,8 @@ namespace Volo.Abp.Json.SystemTextJson { public class SystemTextJsonSupportTypeMatcher : ITransientDependency { - private static readonly ConcurrentBag CacheTypes = new ConcurrentBag(); + private static readonly ConcurrentBag SupportedTypesCache = new ConcurrentBag(); + private static readonly ConcurrentBag UnsupportedTypesCache = new ConcurrentBag(); private readonly SystemTextJsonSupportTypeMatcherOptions _options; @@ -21,25 +22,83 @@ namespace Volo.Abp.Json.SystemTextJson public bool Match(Type type) { - if (_options.UnsupportedTypes.Any(x => x == type)) + if (UnsupportedTypesCache.Contains(type)) { return false; } - if (CacheTypes.Contains(type)) + if (SupportedTypesCache.Contains(type)) { + return true; + } + + if (_options.UnsupportedTypes.Any(x => x == type)) + { + UnsupportedTypesCache.Add(type); return false; } + if (type.IsGenericType) + { + foreach (var genericArgument in type.GetGenericArguments()) + { + if (!TypeHelper.IsPrimitiveExtended(genericArgument, includeNullables: true, includeEnums: true)) + { + if (!Match(genericArgument)) + { + return false; + } + } + else + { + if (_options.UnsupportedTypes.Any(x => x == genericArgument)) + { + UnsupportedTypesCache.Add(genericArgument); + return false; + } + } + } + + return true; + } + + if (type.IsArray) + { + var elementType = type.GetElementType(); + if (!TypeHelper.IsPrimitiveExtended(elementType, includeNullables: true, includeEnums: true)) + { + if (!Match(elementType)) + { + return false; + } + } + else + { + if (_options.UnsupportedTypes.Any(x => x == elementType)) + { + UnsupportedTypesCache.Add(elementType); + return false; + } + } + + return true; + } + + + if (TypeHelper.IsPrimitiveExtended(type, includeNullables: true, includeEnums: true)) + { + return true; + } + if (type.GetCustomAttributes(true).Any(x => _options.UnsupportedAttributes.Any(a => a == x.GetType()))) { - CacheTypes.Add(type); + UnsupportedTypesCache.Add(type); return false; } if (type.DeclaringType != null && type.DeclaringType.GetCustomAttributes(true).Any(x => _options.UnsupportedAttributes.Any(a => a == x.GetType()))) { - CacheTypes.Add(type); + UnsupportedTypesCache.Add(type); return false; } @@ -47,19 +106,76 @@ namespace Volo.Abp.Json.SystemTextJson { if (propertyInfo.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true)) { - CacheTypes.Add(type); + UnsupportedTypesCache.Add(type); + return false; + } + + if (_options.UnsupportedTypes.Any(x => x == propertyInfo.PropertyType)) + { + UnsupportedTypesCache.Add(propertyInfo.PropertyType); return false; } - if (!TypeHelper.IsPrimitiveExtended(type, includeNullables: true, includeEnums: true)) + if (propertyInfo.PropertyType.IsGenericType) + { + foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments()) + { + if (!TypeHelper.IsPrimitiveExtended(genericArgument, includeNullables: true, includeEnums: true)) + { + if (!Match(genericArgument)) + { + return false; + } + } + else + { + if (_options.UnsupportedTypes.Any(x => x == genericArgument)) + { + UnsupportedTypesCache.Add(genericArgument); + return false; + } + } + } + } + + if (propertyInfo.PropertyType.IsArray) + { + var elementType = propertyInfo.PropertyType.GetElementType(); + if (!TypeHelper.IsPrimitiveExtended(elementType, includeNullables: true, includeEnums: true)) + { + if (!Match(elementType)) + { + return false; + } + } + else + { + if (_options.UnsupportedTypes.Any(x => x == elementType)) + { + UnsupportedTypesCache.Add(elementType); + return false; + } + } + } + + if (!TypeHelper.IsPrimitiveExtended(propertyInfo.PropertyType, includeNullables: true, includeEnums: true)) { if (!Match(propertyInfo.PropertyType)) { return false; } } + else + { + if (_options.UnsupportedTypes.Any(x => x == propertyInfo.PropertyType)) + { + UnsupportedTypesCache.Add(propertyInfo.PropertyType); + return false; + } + } } + SupportedTypesCache.Add(type); return true; } } diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypeMatcher_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypeMatcher_Tests.cs index f67431a026..6fdc6fcb94 100644 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypeMatcher_Tests.cs +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypeMatcher_Tests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Json.SystemTextJson; @@ -16,6 +17,7 @@ namespace Volo.Abp.Json services.Configure(options => { options.UnsupportedTypes.Add(); + options.UnsupportedTypes.Add(); }); base.AfterAddApplication(services); @@ -38,6 +40,18 @@ namespace Volo.Abp.Json _systemTextJsonSupportTypeMatcher.Match(typeof(MyClass6)).ShouldBeTrue(); _systemTextJsonSupportTypeMatcher.Match(typeof(MyClass7)).ShouldBeFalse(); + + _systemTextJsonSupportTypeMatcher.Match(typeof(MyClass8)).ShouldBeFalse(); + _systemTextJsonSupportTypeMatcher.Match(typeof(MyClass9)).ShouldBeFalse(); + + _systemTextJsonSupportTypeMatcher.Match(typeof(string)).ShouldBeTrue(); + _systemTextJsonSupportTypeMatcher.Match(typeof(string[])).ShouldBeTrue(); + + _systemTextJsonSupportTypeMatcher.Match(typeof(int)).ShouldBeTrue(); + + _systemTextJsonSupportTypeMatcher.Match(typeof(byte)).ShouldBeFalse(); + _systemTextJsonSupportTypeMatcher.Match(typeof(Dictionary)).ShouldBeFalse(); + _systemTextJsonSupportTypeMatcher.Match(typeof(Dictionary)).ShouldBeFalse(); } [DisableDateTimeNormalization] @@ -79,5 +93,21 @@ namespace Volo.Abp.Json { public DateTime Prop1 { get; set; } } + + class MyClass8 + { + public MyClass10[] Prop1 { get; set; } + } + + class MyClass9 + { + public Dictionary Prop1 { get; set; } + } + + class MyClass10 + { + [DisableDateTimeNormalization] + public DateTime Prop1 { get; set; } + } } }