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