From 1a36b4a996c54f3a262132faedc16131fbbf80a8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 3 Sep 2014 21:06:16 +1200 Subject: [PATCH] -Changed collection parameterized creators to be created only when needed --- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/JsonArrayContract.cs | 37 +++++++++++++++---- .../Serialization/JsonDictionaryContract.cs | 33 ++++++++++++++--- .../JsonSerializerInternalReader.cs | 8 ++-- .../Utilities/CollectionUtils.cs | 7 +--- 6 files changed, 66 insertions(+), 23 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index aed2b78f..439da49a 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -75,4 +75,4 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.4.17631")] +[assembly: AssemblyFileVersion("6.0.4.17703")] diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index b90d57ef..1c7dca5f 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -91,5 +91,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.4.17631")] +[assembly: AssemblyFileVersion("6.0.4.17703")] [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs b/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs index fe4c40b0..e5f540be 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs @@ -66,7 +66,30 @@ namespace Newtonsoft.Json.Serialization internal bool IsArray { get; private set; } internal bool ShouldCreateWrapper { get; private set; } internal bool CanDeserialize { get; private set; } - internal ObjectConstructor ParametrizedCreator { get; private set; } + + private readonly ConstructorInfo _parametrizedConstructor; + + private ObjectConstructor _parametrizedCreator; + internal ObjectConstructor ParametrizedCreator + { + get + { + if (_parametrizedCreator == null) + { + if (_parametrizedConstructor == null) + return null; + + _parametrizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParametrizedConstructor(_parametrizedConstructor); + } + + return _parametrizedCreator; + } + } + + internal bool HasParametrizedCreator + { + get { return _parametrizedCreator != null || _parametrizedConstructor != null; } + } /// /// Initializes a new instance of the class. @@ -101,7 +124,7 @@ namespace Newtonsoft.Json.Serialization CreatedType = typeof(List); if (CollectionItemType != null) - ParametrizedCreator = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType); + _parametrizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType); IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>)); canDeserialize = true; @@ -119,7 +142,7 @@ namespace Newtonsoft.Json.Serialization CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType); #endif - ParametrizedCreator = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType); + _parametrizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType); canDeserialize = true; ShouldCreateWrapper = true; } @@ -133,7 +156,7 @@ namespace Newtonsoft.Json.Serialization CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType); _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); - ParametrizedCreator = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, CollectionItemType); + _parametrizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, CollectionItemType); IsReadOnlyOrFixedSize = true; canDeserialize = (ParametrizedCreator != null); } @@ -145,13 +168,13 @@ namespace Newtonsoft.Json.Serialization if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IEnumerable<>))) CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); - ParametrizedCreator = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType); + _parametrizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType); #if !(NET35 || NET20 || NETFX_CORE) if (ParametrizedCreator == null && underlyingType.Name == FSharpUtils.FSharpListTypeName) { FSharpUtils.EnsureInitialized(underlyingType.Assembly()); - ParametrizedCreator = FSharpUtils.CreateSeq(CollectionItemType); + _parametrizedCreator = FSharpUtils.CreateSeq(CollectionItemType); } #endif @@ -200,7 +223,7 @@ namespace Newtonsoft.Json.Serialization if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(underlyingType, CollectionItemType, out immutableCreatedType, out immutableParameterizedCreator)) { CreatedType = immutableCreatedType; - ParametrizedCreator = immutableParameterizedCreator; + _parametrizedCreator = immutableParameterizedCreator; IsReadOnlyOrFixedSize = true; CanDeserialize = true; } diff --git a/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs b/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs index 25759258..5da22eb3 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs @@ -69,7 +69,30 @@ namespace Newtonsoft.Json.Serialization private Func _genericTemporaryDictionaryCreator; internal bool ShouldCreateWrapper { get; private set; } - internal ObjectConstructor ParametrizedCreator { get; private set; } + + private readonly ConstructorInfo _parametrizedConstructor; + + private ObjectConstructor _parametrizedCreator; + internal ObjectConstructor ParametrizedCreator + { + get + { + if (_parametrizedCreator == null) + { + if (_parametrizedConstructor == null) + return null; + + _parametrizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParametrizedConstructor(_parametrizedConstructor); + } + + return _parametrizedCreator; + } + } + + internal bool HasParametrizedCreator + { + get { return _parametrizedCreator != null || _parametrizedConstructor != null; } + } /// /// Initializes a new instance of the class. @@ -117,13 +140,13 @@ namespace Newtonsoft.Json.Serialization if (keyType != null && valueType != null) { - ParametrizedCreator = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType)); + _parametrizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType)); #if !(NET35 || NET20 || NETFX_CORE) - if (ParametrizedCreator == null && underlyingType.Name == FSharpUtils.FSharpMapTypeName) + if (_parametrizedConstructor == null && underlyingType.Name == FSharpUtils.FSharpMapTypeName) { FSharpUtils.EnsureInitialized(underlyingType.Assembly()); - ParametrizedCreator = FSharpUtils.CreateMap(keyType, valueType); + _parametrizedCreator = FSharpUtils.CreateMap(keyType, valueType); } #endif } @@ -153,7 +176,7 @@ namespace Newtonsoft.Json.Serialization if (ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract(underlyingType, DictionaryKeyType, DictionaryValueType, out immutableCreatedType, out immutableParameterizedCreator)) { CreatedType = immutableCreatedType; - ParametrizedCreator = immutableParameterizedCreator; + _parametrizedCreator = immutableParameterizedCreator; IsReadOnlyOrFixedSize = true; } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 2d51728b..0d1e6a38 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -487,7 +487,7 @@ namespace Newtonsoft.Json.Serialization if (contract.OnErrorCallbacks.Count > 0) throw JsonSerializationException.Create(reader, "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - if (dictionaryContract.ParametrizedCreator == null) + if (!dictionaryContract.HasParametrizedCreator) throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } @@ -783,7 +783,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ if (contract.OnErrorCallbacks.Count > 0) throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - if (arrayContract.ParametrizedCreator == null && !arrayContract.IsArray) + if (!arrayContract.HasParametrizedCreator && !arrayContract.IsArray) throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } @@ -1053,7 +1053,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ createdFromNonDefaultCreator = false; return (IList)list; } - else if (contract.ParametrizedCreator != null) + else if (contract.HasParametrizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryCollection(); @@ -1084,7 +1084,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ createdFromNonDefaultCreator = false; return (IDictionary)dictionary; } - else if (contract.ParametrizedCreator != null) + else if (contract.HasParametrizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); diff --git a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs index 2230e4db..338b132c 100644 --- a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs @@ -102,7 +102,7 @@ namespace Newtonsoft.Json.Utilities return false; } - public static ObjectConstructor ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) + public static ConstructorInfo ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) { Type genericEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionItemType); ConstructorInfo match = null; @@ -129,10 +129,7 @@ namespace Newtonsoft.Json.Utilities } } - if (match != null) - return JsonTypeReflector.ReflectionDelegateFactory.CreateParametrizedConstructor(match); - - return null; + return match; } public static bool AddDistinct(this IList list, T value)