mirror of https://github.com/abpframework/abp.git
14 changed files with 165 additions and 332 deletions
@ -0,0 +1,21 @@ |
|||||
|
using System; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Json.SystemTextJson |
||||
|
{ |
||||
|
public class AbpSystemTextJsonSupportTypeMatcher : ITransientDependency |
||||
|
{ |
||||
|
protected AbpSystemTextJsonSupportTypeMatcherOptions Options { get; } |
||||
|
|
||||
|
public AbpSystemTextJsonSupportTypeMatcher(IOptions<AbpSystemTextJsonSupportTypeMatcherOptions> options) |
||||
|
{ |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public virtual bool Match(Type type) |
||||
|
{ |
||||
|
return !Options.UnsupportedTypes.Contains(type); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.Collections; |
||||
|
|
||||
|
namespace Volo.Abp.Json.SystemTextJson |
||||
|
{ |
||||
|
public class AbpSystemTextJsonSupportTypeMatcherOptions |
||||
|
{ |
||||
|
public ITypeList UnsupportedTypes { get; } |
||||
|
|
||||
|
public AbpSystemTextJsonSupportTypeMatcherOptions() |
||||
|
{ |
||||
|
UnsupportedTypes = new TypeList(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,182 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Concurrent; |
|
||||
using System.Linq; |
|
||||
using Microsoft.Extensions.Options; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Reflection; |
|
||||
using Volo.Abp.Timing; |
|
||||
|
|
||||
namespace Volo.Abp.Json.SystemTextJson |
|
||||
{ |
|
||||
public class SystemTextJsonSupportTypeMatcher : ITransientDependency |
|
||||
{ |
|
||||
private static readonly ConcurrentBag<Type> SupportedTypesCache = new ConcurrentBag<Type>(); |
|
||||
private static readonly ConcurrentBag<Type> UnsupportedTypesCache = new ConcurrentBag<Type>(); |
|
||||
|
|
||||
private readonly SystemTextJsonSupportTypeMatcherOptions _options; |
|
||||
|
|
||||
public SystemTextJsonSupportTypeMatcher(IOptions<SystemTextJsonSupportTypeMatcherOptions> options) |
|
||||
{ |
|
||||
_options = options.Value; |
|
||||
} |
|
||||
|
|
||||
public bool Match(Type type) |
|
||||
{ |
|
||||
if (UnsupportedTypesCache.Contains(type)) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
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()))) |
|
||||
{ |
|
||||
UnsupportedTypesCache.Add(type); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
if (type.DeclaringType != null && type.DeclaringType.GetCustomAttributes(true).Any(x => _options.UnsupportedAttributes.Any(a => a == x.GetType()))) |
|
||||
{ |
|
||||
UnsupportedTypesCache.Add(type); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
foreach (var propertyInfo in type.GetProperties()) |
|
||||
{ |
|
||||
if (propertyInfo.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true)) |
|
||||
{ |
|
||||
UnsupportedTypesCache.Add(type); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
if (_options.UnsupportedTypes.Any(x => x == propertyInfo.PropertyType)) |
|
||||
{ |
|
||||
UnsupportedTypesCache.Add(propertyInfo.PropertyType); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp.Collections; |
|
||||
|
|
||||
namespace Volo.Abp.Json.SystemTextJson |
|
||||
{ |
|
||||
public class SystemTextJsonSupportTypeMatcherOptions |
|
||||
{ |
|
||||
public ITypeList<Attribute> UnsupportedAttributes { get; } |
|
||||
|
|
||||
public ITypeList UnsupportedTypes { get; } |
|
||||
|
|
||||
public SystemTextJsonSupportTypeMatcherOptions() |
|
||||
{ |
|
||||
UnsupportedAttributes = new TypeList<Attribute>(); |
|
||||
UnsupportedTypes = new TypeList(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,66 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Json.SystemTextJson; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Json |
||||
|
{ |
||||
|
public class AbpSystemTextJsonSupportTypeMatcher_Tests : AbpJsonTestBase |
||||
|
{ |
||||
|
private readonly AbpSystemTextJsonSupportTypeMatcher _abpSystemTextJsonSupportTypeMatcher; |
||||
|
|
||||
|
public AbpSystemTextJsonSupportTypeMatcher_Tests() |
||||
|
{ |
||||
|
_abpSystemTextJsonSupportTypeMatcher = GetRequiredService<AbpSystemTextJsonSupportTypeMatcher>(); |
||||
|
} |
||||
|
|
||||
|
protected override void AfterAddApplication(IServiceCollection services) |
||||
|
{ |
||||
|
services.Configure<AbpSystemTextJsonSupportTypeMatcherOptions>(options => |
||||
|
{ |
||||
|
options.UnsupportedTypes.Add<MyClass>(); |
||||
|
options.UnsupportedTypes.Add<byte[]>(); |
||||
|
options.UnsupportedTypes.Add<Dictionary<string, MyClass4>>(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanHandle_Test() |
||||
|
{ |
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(MyClass)).ShouldBeFalse(); |
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(byte[])).ShouldBeFalse(); |
||||
|
|
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(MyClass2)).ShouldBeTrue(); |
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(MyClass3)).ShouldBeTrue(); |
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(MyClass4)).ShouldBeTrue(); |
||||
|
|
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(string)).ShouldBeTrue(); |
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(string[])).ShouldBeTrue(); |
||||
|
|
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(Dictionary<string, MyClass4>)).ShouldBeFalse(); |
||||
|
_abpSystemTextJsonSupportTypeMatcher.Match(typeof(IDictionary<string, MyClass4>)).ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
class MyClass |
||||
|
{ |
||||
|
public DateTime Prop1 { get; set; } |
||||
|
} |
||||
|
|
||||
|
class MyClass2 |
||||
|
{ |
||||
|
public DateTime Prop1 { get; set; } |
||||
|
} |
||||
|
|
||||
|
class MyClass3 |
||||
|
{ |
||||
|
public MyClass4 Prop1 { get; set; } |
||||
|
} |
||||
|
|
||||
|
class MyClass4 |
||||
|
{ |
||||
|
public DateTime Prop1 { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,113 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Shouldly; |
|
||||
using Volo.Abp.Json.SystemTextJson; |
|
||||
using Volo.Abp.Timing; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.Json |
|
||||
{ |
|
||||
public class SystemTextJsonSupportTypeMatcher_Tests : AbpJsonTestBase |
|
||||
{ |
|
||||
private readonly SystemTextJsonSupportTypeMatcher _systemTextJsonSupportTypeMatcher; |
|
||||
|
|
||||
protected override void AfterAddApplication(IServiceCollection services) |
|
||||
{ |
|
||||
services.Configure<SystemTextJsonSupportTypeMatcherOptions>(options => |
|
||||
{ |
|
||||
options.UnsupportedTypes.Add<MyClass7>(); |
|
||||
options.UnsupportedTypes.Add<byte>(); |
|
||||
}); |
|
||||
|
|
||||
base.AfterAddApplication(services); |
|
||||
} |
|
||||
|
|
||||
public SystemTextJsonSupportTypeMatcher_Tests() |
|
||||
{ |
|
||||
_systemTextJsonSupportTypeMatcher = GetRequiredService<SystemTextJsonSupportTypeMatcher>(); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanHandle_Test() |
|
||||
{ |
|
||||
_systemTextJsonSupportTypeMatcher.Match(typeof(MyClass)).ShouldBeFalse(); |
|
||||
_systemTextJsonSupportTypeMatcher.Match(typeof(MyClass2)).ShouldBeFalse(); |
|
||||
_systemTextJsonSupportTypeMatcher.Match(typeof(MyClass3)).ShouldBeFalse(); |
|
||||
_systemTextJsonSupportTypeMatcher.Match(typeof(MyClass4)).ShouldBeFalse(); |
|
||||
|
|
||||
_systemTextJsonSupportTypeMatcher.Match(typeof(MyClass5)).ShouldBeTrue(); |
|
||||
_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<byte, byte>)).ShouldBeFalse(); |
|
||||
_systemTextJsonSupportTypeMatcher.Match(typeof(Dictionary<string, MyClass10>)).ShouldBeFalse(); |
|
||||
} |
|
||||
|
|
||||
[DisableDateTimeNormalization] |
|
||||
class MyClass |
|
||||
{ |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass2 |
|
||||
{ |
|
||||
[DisableDateTimeNormalization] |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass3 |
|
||||
{ |
|
||||
public MyClass4 Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass4 |
|
||||
{ |
|
||||
[DisableDateTimeNormalization] |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass5 |
|
||||
{ |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
|
|
||||
public MyClass6 Prop2 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass6 |
|
||||
{ |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass7 |
|
||||
{ |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass8 |
|
||||
{ |
|
||||
public MyClass10[] Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass9 |
|
||||
{ |
|
||||
public Dictionary<string, MyClass10> Prop1 { get; set; } |
|
||||
} |
|
||||
|
|
||||
class MyClass10 |
|
||||
{ |
|
||||
[DisableDateTimeNormalization] |
|
||||
public DateTime Prop1 { get; set; } |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue