-Changed collection parameterized creators to be created only when needed

This commit is contained in:
James Newton-King
2014-09-03 21:06:16 +12:00
parent 0c865efd96
commit 1a36b4a996
6 changed files with 66 additions and 23 deletions
@@ -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")]
@@ -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)]
@@ -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<object> ParametrizedCreator { get; private set; }
private readonly ConstructorInfo _parametrizedConstructor;
private ObjectConstructor<object> _parametrizedCreator;
internal ObjectConstructor<object> 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; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonArrayContract"/> class.
@@ -101,7 +124,7 @@ namespace Newtonsoft.Json.Serialization
CreatedType = typeof(List<object>);
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;
}
@@ -69,7 +69,30 @@ namespace Newtonsoft.Json.Serialization
private Func<object> _genericTemporaryDictionaryCreator;
internal bool ShouldCreateWrapper { get; private set; }
internal ObjectConstructor<object> ParametrizedCreator { get; private set; }
private readonly ConstructorInfo _parametrizedConstructor;
private ObjectConstructor<object> _parametrizedCreator;
internal ObjectConstructor<object> 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; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonDictionaryContract"/> 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
@@ -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();
@@ -102,7 +102,7 @@ namespace Newtonsoft.Json.Utilities
return false;
}
public static ObjectConstructor<object> 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<T>(this IList<T> list, T value)