From e27de68142d4592806a00d1e0616233b0013ea41 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 19 Jul 2019 10:37:54 +0800 Subject: [PATCH 1/4] Resolve #1503 Reuse Contract Resolver, improve performance. --- .../Volo/Abp/Auditing/AuditingContractResolver.cs | 11 ++++++++++- .../Volo/Abp/Auditing/JsonNetAuditSerializer.cs | 2 +- .../Client/DynamicProxying/ApiDescriptionFinder.cs | 5 ++++- .../Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs | 5 ++++- .../Json/JsonLocalizationDictionaryBuilder.cs | 7 +++++-- .../Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs | 5 ++++- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs index 24f86ce0b4..0f10652d8d 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; using Newtonsoft.Json; @@ -35,5 +36,13 @@ namespace Volo.Abp.Auditing return property; } + + private static readonly ConcurrentDictionary, AuditingContractResolver> AuditingContractResolverdDictionary = new ConcurrentDictionary, AuditingContractResolver>(); + + public static AuditingContractResolver GetSharedAuditingContractResolver(List ignoredTypes) + { + return AuditingContractResolverdDictionary.GetOrAdd(ignoredTypes, + x => new AuditingContractResolver(ignoredTypes)); + } } } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs index 3862dd01da..931cdbbfad 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs @@ -18,7 +18,7 @@ namespace Volo.Abp.Auditing { var options = new JsonSerializerSettings { - ContractResolver = new AuditingContractResolver(Options.IgnoredTypes) + ContractResolver = AuditingContractResolver.GetSharedAuditingContractResolver(Options.IgnoredTypes) }; return JsonConvert.SerializeObject(obj, options); diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs index 4114b89892..885382b335 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs @@ -18,6 +18,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying protected IApiDescriptionCache Cache { get; } + private static readonly CamelCasePropertyNamesContractResolver SharedCamelCasePropertyNamesContractResolver = + new CamelCasePropertyNamesContractResolver(); + public ApiDescriptionFinder( IApiDescriptionCache cache, IDynamicProxyHttpClientFactory httpClientFactory) @@ -97,7 +100,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying typeof(ApplicationApiDescriptionModel), new JsonSerializerSettings { - ContractResolver = new CamelCasePropertyNamesContractResolver() + ContractResolver = SharedCamelCasePropertyNamesContractResolver }); return (ApplicationApiDescriptionModel)result; diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs index 262c2b04d7..99252b8448 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs @@ -9,6 +9,9 @@ namespace Volo.Abp.Json.Newtonsoft { private readonly AbpJsonIsoDateTimeConverter _dateTimeConverter; + private static readonly CamelCaseExceptDictionaryKeysResolver SharedCamelCaseExceptDictionaryKeysResolver = + new CamelCaseExceptDictionaryKeysResolver(); + public NewtonsoftJsonSerializer(AbpJsonIsoDateTimeConverter dateTimeConverter) { _dateTimeConverter = dateTimeConverter; @@ -37,7 +40,7 @@ namespace Volo.Abp.Json.Newtonsoft if (camelCase) { - settings.ContractResolver = new CamelCaseExceptDictionaryKeysResolver(); + settings.ContractResolver = SharedCamelCaseExceptDictionaryKeysResolver; } if (indented) diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs index 325d67800d..78e16480b7 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using Microsoft.Extensions.Localization; @@ -9,6 +9,9 @@ namespace Volo.Abp.Localization.Json { public static class JsonLocalizationDictionaryBuilder { + private static readonly CamelCasePropertyNamesContractResolver SharedCamelCasePropertyNamesContractResolver = + new CamelCasePropertyNamesContractResolver(); + /// /// Builds an from given file. /// @@ -38,7 +41,7 @@ namespace Volo.Abp.Localization.Json jsonString, new JsonSerializerSettings { - ContractResolver = new CamelCasePropertyNamesContractResolver() + ContractResolver = SharedCamelCasePropertyNamesContractResolver }); } catch (JsonException ex) diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs index 6bb82c3656..4d0dc01776 100644 --- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs +++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs @@ -11,12 +11,15 @@ namespace Volo.Abp.AspNetCore public abstract class AbpAspNetCoreTestBase : AbpAspNetCoreIntegratedTestBase where TStartup : class { + private static readonly CamelCasePropertyNamesContractResolver SharedCamelCasePropertyNamesContractResolver = + new CamelCasePropertyNamesContractResolver(); + protected virtual async Task GetResponseAsObjectAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) { var strResponse = await GetResponseAsStringAsync(url, expectedStatusCode); return JsonConvert.DeserializeObject(strResponse, new JsonSerializerSettings { - ContractResolver = new CamelCasePropertyNamesContractResolver() + ContractResolver = SharedCamelCasePropertyNamesContractResolver }); } From 29ac532cb5d7c43a08bdd2b197add0172217afd1 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 19 Jul 2019 16:53:23 +0800 Subject: [PATCH 2/4] Move GetSharedAuditingContractResolver to the JsonNetAuditSerializer class. --- .../Abp/Auditing/AuditingContractResolver.cs | 9 -------- .../Abp/Auditing/JsonNetAuditSerializer.cs | 23 ++++++++++++++++++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs index 0f10652d8d..e6d03bf707 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; using Newtonsoft.Json; @@ -36,13 +35,5 @@ namespace Volo.Abp.Auditing return property; } - - private static readonly ConcurrentDictionary, AuditingContractResolver> AuditingContractResolverdDictionary = new ConcurrentDictionary, AuditingContractResolver>(); - - public static AuditingContractResolver GetSharedAuditingContractResolver(List ignoredTypes) - { - return AuditingContractResolverdDictionary.GetOrAdd(ignoredTypes, - x => new AuditingContractResolver(ignoredTypes)); - } } } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs index 931cdbbfad..6da7ec5da2 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections.Generic; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Volo.Abp.DependencyInjection; @@ -18,10 +20,29 @@ namespace Volo.Abp.Auditing { var options = new JsonSerializerSettings { - ContractResolver = AuditingContractResolver.GetSharedAuditingContractResolver(Options.IgnoredTypes) + ContractResolver = GetSharedAuditingContractResolver(Options.IgnoredTypes) }; return JsonConvert.SerializeObject(obj, options); } + + private static readonly object SyncObj = new object(); + private static AuditingContractResolver _sharedAuditingContractResolver; + + public static AuditingContractResolver GetSharedAuditingContractResolver(List ignoredTypes) + { + if (_sharedAuditingContractResolver == null) + { + lock (SyncObj) + { + if (_sharedAuditingContractResolver == null) + { + _sharedAuditingContractResolver = new AuditingContractResolver(ignoredTypes); + } + } + } + + return _sharedAuditingContractResolver; + } } } \ No newline at end of file From 743c80bc18d4339141400967bfbe91ed93366683 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 23 Jul 2019 17:33:46 +0800 Subject: [PATCH 3/4] Reuse shared JsonSerializerSettings instead of shared ContractResolver. --- .../Abp/Auditing/JsonNetAuditSerializer.cs | 24 ++++++-------- .../DynamicProxying/ApiDescriptionFinder.cs | 31 ++++++++++++++----- .../Json/JsonLocalizationDictionaryBuilder.cs | 12 +++---- .../Abp/AspNetCore/AbpAspNetCoreTestBase.cs | 12 +++---- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs index 6da7ec5da2..b86df6b6c8 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Volo.Abp.DependencyInjection; @@ -18,31 +16,29 @@ namespace Volo.Abp.Auditing public string Serialize(object obj) { - var options = new JsonSerializerSettings - { - ContractResolver = GetSharedAuditingContractResolver(Options.IgnoredTypes) - }; - - return JsonConvert.SerializeObject(obj, options); + return JsonConvert.SerializeObject(obj, GetSharedJsonSerializerSettings()); } private static readonly object SyncObj = new object(); - private static AuditingContractResolver _sharedAuditingContractResolver; + private static JsonSerializerSettings _sharedJsonSerializerSettings; - public static AuditingContractResolver GetSharedAuditingContractResolver(List ignoredTypes) + private JsonSerializerSettings GetSharedJsonSerializerSettings() { - if (_sharedAuditingContractResolver == null) + if (_sharedJsonSerializerSettings == null) { lock (SyncObj) { - if (_sharedAuditingContractResolver == null) + if (_sharedJsonSerializerSettings == null) { - _sharedAuditingContractResolver = new AuditingContractResolver(ignoredTypes); + _sharedJsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new AuditingContractResolver(Options.IgnoredTypes) + }; } } } - return _sharedAuditingContractResolver; + return _sharedJsonSerializerSettings; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs index 885382b335..d8d0204555 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs @@ -18,9 +18,6 @@ namespace Volo.Abp.Http.Client.DynamicProxying protected IApiDescriptionCache Cache { get; } - private static readonly CamelCasePropertyNamesContractResolver SharedCamelCasePropertyNamesContractResolver = - new CamelCasePropertyNamesContractResolver(); - public ApiDescriptionFinder( IApiDescriptionCache cache, IDynamicProxyHttpClientFactory httpClientFactory) @@ -97,14 +94,32 @@ namespace Volo.Abp.Http.Client.DynamicProxying var result = JsonConvert.DeserializeObject( content, - typeof(ApplicationApiDescriptionModel), - new JsonSerializerSettings - { - ContractResolver = SharedCamelCasePropertyNamesContractResolver - }); + typeof(ApplicationApiDescriptionModel), GetSharedJsonSerializerSettings()); return (ApplicationApiDescriptionModel)result; } } + + private static readonly object SyncObj = new object(); + private static JsonSerializerSettings _sharedJsonSerializerSettings; + + private static JsonSerializerSettings GetSharedJsonSerializerSettings() + { + if (_sharedJsonSerializerSettings == null) + { + lock (SyncObj) + { + if (_sharedJsonSerializerSettings == null) + { + _sharedJsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; + } + } + } + + return _sharedJsonSerializerSettings; + } } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs index 78e16480b7..9b1f1617f6 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs @@ -9,8 +9,10 @@ namespace Volo.Abp.Localization.Json { public static class JsonLocalizationDictionaryBuilder { - private static readonly CamelCasePropertyNamesContractResolver SharedCamelCasePropertyNamesContractResolver = - new CamelCasePropertyNamesContractResolver(); + private static readonly JsonSerializerSettings SharedJsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; /// /// Builds an from given file. @@ -38,11 +40,7 @@ namespace Volo.Abp.Localization.Json try { jsonFile = JsonConvert.DeserializeObject( - jsonString, - new JsonSerializerSettings - { - ContractResolver = SharedCamelCasePropertyNamesContractResolver - }); + jsonString, SharedJsonSerializerSettings); } catch (JsonException ex) { diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs index 4d0dc01776..33beb9d62c 100644 --- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs +++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs @@ -11,16 +11,16 @@ namespace Volo.Abp.AspNetCore public abstract class AbpAspNetCoreTestBase : AbpAspNetCoreIntegratedTestBase where TStartup : class { - private static readonly CamelCasePropertyNamesContractResolver SharedCamelCasePropertyNamesContractResolver = - new CamelCasePropertyNamesContractResolver(); + private static readonly JsonSerializerSettings SharedJsonSerializerSettings = + new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; protected virtual async Task GetResponseAsObjectAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) { var strResponse = await GetResponseAsStringAsync(url, expectedStatusCode); - return JsonConvert.DeserializeObject(strResponse, new JsonSerializerSettings - { - ContractResolver = SharedCamelCasePropertyNamesContractResolver - }); + return JsonConvert.DeserializeObject(strResponse, SharedJsonSerializerSettings); } protected virtual async Task GetResponseAsStringAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) From ed0934f7f4ef84f7263f2068aed842a29664d8ba Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 24 Jul 2019 08:32:20 +0800 Subject: [PATCH 4/4] ApiDescriptionFinder uses static JsonSerializerSettings directly. --- .../DynamicProxying/ApiDescriptionFinder.cs | 29 ++++--------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs index d8d0204555..882bf94cb0 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs @@ -18,6 +18,11 @@ namespace Volo.Abp.Http.Client.DynamicProxying protected IApiDescriptionCache Cache { get; } + private static readonly JsonSerializerSettings SharedJsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; + public ApiDescriptionFinder( IApiDescriptionCache cache, IDynamicProxyHttpClientFactory httpClientFactory) @@ -94,32 +99,10 @@ namespace Volo.Abp.Http.Client.DynamicProxying var result = JsonConvert.DeserializeObject( content, - typeof(ApplicationApiDescriptionModel), GetSharedJsonSerializerSettings()); + typeof(ApplicationApiDescriptionModel), SharedJsonSerializerSettings); return (ApplicationApiDescriptionModel)result; } } - - private static readonly object SyncObj = new object(); - private static JsonSerializerSettings _sharedJsonSerializerSettings; - - private static JsonSerializerSettings GetSharedJsonSerializerSettings() - { - if (_sharedJsonSerializerSettings == null) - { - lock (SyncObj) - { - if (_sharedJsonSerializerSettings == null) - { - _sharedJsonSerializerSettings = new JsonSerializerSettings - { - ContractResolver = new CamelCasePropertyNamesContractResolver() - }; - } - } - } - - return _sharedJsonSerializerSettings; - } } }