-Parameterized object creation refactor
This commit is contained in:
@@ -67,7 +67,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
internal bool IsArray { get; private set; }
|
internal bool IsArray { get; private set; }
|
||||||
internal bool ShouldCreateWrapper { get; private set; }
|
internal bool ShouldCreateWrapper { get; private set; }
|
||||||
internal bool CanDeserialize { get; private set; }
|
internal bool CanDeserialize { get; private set; }
|
||||||
internal MethodCall<object, object> ParametrizedConstructor { get; private set; }
|
internal MethodCall<object, object> ParametrizedCreator { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="JsonArrayContract"/> class.
|
/// Initializes a new instance of the <see cref="JsonArrayContract"/> class.
|
||||||
@@ -102,7 +102,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
CreatedType = typeof(List<object>);
|
CreatedType = typeof(List<object>);
|
||||||
|
|
||||||
if (CollectionItemType != null)
|
if (CollectionItemType != null)
|
||||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
ParametrizedCreator = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||||
|
|
||||||
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>));
|
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>));
|
||||||
canDeserialize = true;
|
canDeserialize = true;
|
||||||
@@ -120,7 +120,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType);
|
CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
ParametrizedCreator = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||||
canDeserialize = true;
|
canDeserialize = true;
|
||||||
ShouldCreateWrapper = true;
|
ShouldCreateWrapper = true;
|
||||||
}
|
}
|
||||||
@@ -134,9 +134,9 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType);
|
CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType);
|
||||||
|
|
||||||
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
|
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
|
||||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(CreatedType, CollectionItemType);
|
ParametrizedCreator = CollectionUtils.ResolveEnumableCollectionConstructor(CreatedType, CollectionItemType);
|
||||||
IsReadOnlyOrFixedSize = true;
|
IsReadOnlyOrFixedSize = true;
|
||||||
canDeserialize = (ParametrizedConstructor != null);
|
canDeserialize = (ParametrizedCreator != null);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IEnumerable<>), out tempCollectionType))
|
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IEnumerable<>), out tempCollectionType))
|
||||||
@@ -146,13 +146,13 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IEnumerable<>)))
|
if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IEnumerable<>)))
|
||||||
CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
|
CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
|
||||||
|
|
||||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
ParametrizedCreator = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||||
|
|
||||||
#if !(NET35 || NET20 || NETFX_CORE)
|
#if !(NET35 || NET20 || NETFX_CORE)
|
||||||
if (ParametrizedConstructor == null && underlyingType.Name == FSharpUtils.FSharpListTypeName)
|
if (ParametrizedCreator == null && underlyingType.Name == FSharpUtils.FSharpListTypeName)
|
||||||
{
|
{
|
||||||
FSharpUtils.EnsureInitialized(underlyingType.Assembly());
|
FSharpUtils.EnsureInitialized(underlyingType.Assembly());
|
||||||
ParametrizedConstructor = FSharpUtils.CreateSeq(CollectionItemType);
|
ParametrizedCreator = FSharpUtils.CreateSeq(CollectionItemType);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
|
|
||||||
IsReadOnlyOrFixedSize = true;
|
IsReadOnlyOrFixedSize = true;
|
||||||
ShouldCreateWrapper = true;
|
ShouldCreateWrapper = true;
|
||||||
canDeserialize = (ParametrizedConstructor != null);
|
canDeserialize = (ParametrizedCreator != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -202,7 +202,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(underlyingType, CollectionItemType, out immutableCreatedType, out immutableParameterizedCreator))
|
if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(underlyingType, CollectionItemType, out immutableCreatedType, out immutableParameterizedCreator))
|
||||||
{
|
{
|
||||||
CreatedType = immutableCreatedType;
|
CreatedType = immutableCreatedType;
|
||||||
ParametrizedConstructor = immutableParameterizedCreator;
|
ParametrizedCreator = immutableParameterizedCreator;
|
||||||
IsReadOnlyOrFixedSize = true;
|
IsReadOnlyOrFixedSize = true;
|
||||||
CanDeserialize = true;
|
CanDeserialize = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,13 +68,31 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
/// JsonConstructor attribute.
|
/// JsonConstructor attribute.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The override constructor.</value>
|
/// <value>The override constructor.</value>
|
||||||
public ConstructorInfo OverrideConstructor { get; set; }
|
public ConstructorInfo OverrideConstructor
|
||||||
|
{
|
||||||
|
get { return _overrideConstructor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_overrideConstructor = value;
|
||||||
|
ParametrizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the parametrized constructor used to create the object.
|
/// Gets or sets the parametrized constructor used to create the object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The parametrized constructor.</value>
|
/// <value>The parametrized constructor.</value>
|
||||||
public ConstructorInfo ParametrizedConstructor { get; set; }
|
public ConstructorInfo ParametrizedConstructor
|
||||||
|
{
|
||||||
|
get { return _parametrizedConstructor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_parametrizedConstructor = value;
|
||||||
|
ParametrizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal MethodCall<object, object> ParametrizedCreator { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the extension data setter.
|
/// Gets or sets the extension data setter.
|
||||||
@@ -87,6 +105,8 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
public ExtensionDataGetter ExtensionDataGetter { get; set; }
|
public ExtensionDataGetter ExtensionDataGetter { get; set; }
|
||||||
|
|
||||||
private bool? _hasRequiredOrDefaultValueProperties;
|
private bool? _hasRequiredOrDefaultValueProperties;
|
||||||
|
private ConstructorInfo _parametrizedConstructor;
|
||||||
|
private ConstructorInfo _overrideConstructor;
|
||||||
|
|
||||||
internal bool HasRequiredOrDefaultValueProperties
|
internal bool HasRequiredOrDefaultValueProperties
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
if (contract.OnErrorCallbacks.Count > 0)
|
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));
|
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.ParametrizedConstructor == null)
|
if (dictionaryContract.ParametrizedCreator == null)
|
||||||
throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +471,7 @@ namespace Newtonsoft.Json.Serialization
|
|||||||
|
|
||||||
if (createdFromNonDefaultConstructor)
|
if (createdFromNonDefaultConstructor)
|
||||||
{
|
{
|
||||||
return dictionaryContract.ParametrizedConstructor(null , new object[] { dictionary });
|
return dictionaryContract.ParametrizedCreator(null , new object[] { dictionary });
|
||||||
}
|
}
|
||||||
else if (dictionary is IWrappedDictionary)
|
else if (dictionary is IWrappedDictionary)
|
||||||
{
|
{
|
||||||
@@ -1057,7 +1057,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
|||||||
createdFromNonDefaultConstructor = false;
|
createdFromNonDefaultConstructor = false;
|
||||||
return (IDictionary)dictionary;
|
return (IDictionary)dictionary;
|
||||||
}
|
}
|
||||||
else if (contract.ParametrizedConstructor != null)
|
else if (contract.ParametrizedCreator != null)
|
||||||
{
|
{
|
||||||
createdFromNonDefaultConstructor = true;
|
createdFromNonDefaultConstructor = true;
|
||||||
return contract.CreateTemporaryDictionary();
|
return contract.CreateTemporaryDictionary();
|
||||||
@@ -1568,7 +1568,7 @@ To fix this error either change the environment to be fully trusted, change the
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id)
|
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, MethodCall<object, object> constructorInfo, string id)
|
||||||
{
|
{
|
||||||
ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");
|
ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");
|
||||||
|
|
||||||
@@ -1580,17 +1580,20 @@ To fix this error either change the environment to be fully trusted, change the
|
|||||||
Type objectType = contract.UnderlyingType;
|
Type objectType = contract.UnderlyingType;
|
||||||
|
|
||||||
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
|
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
|
||||||
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using a non-default constructor '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, constructorInfo)), null);
|
{
|
||||||
|
string underlyingMethodName = constructorInfo.GetMethodInfo().Name;
|
||||||
|
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using custom method '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, underlyingMethodName)), null);
|
||||||
|
}
|
||||||
|
|
||||||
IDictionary<string, object> extensionData;
|
IDictionary<string, object> extensionData;
|
||||||
IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType, out extensionData);
|
IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType, out extensionData);
|
||||||
|
|
||||||
IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object)null);
|
IDictionary<JsonProperty, object> constructorParameters = contract.ConstructorParameters.ToDictionary(p => p, p => (object)null);
|
||||||
IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();
|
IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();
|
||||||
|
|
||||||
foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
|
foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
|
||||||
{
|
{
|
||||||
ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, propertyValue.Key.UnderlyingName).Key;
|
JsonProperty matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.PropertyName, propertyValue.Key.UnderlyingName).Key;
|
||||||
if (matchingConstructorParameter != null)
|
if (matchingConstructorParameter != null)
|
||||||
constructorParameters[matchingConstructorParameter] = propertyValue.Value;
|
constructorParameters[matchingConstructorParameter] = propertyValue.Value;
|
||||||
else
|
else
|
||||||
@@ -1605,7 +1608,7 @@ To fix this error either change the environment to be fully trusted, change the
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object createdObject = constructorInfo.Invoke(constructorParameters.Values.ToArray());
|
object createdObject = constructorInfo(null, constructorParameters.Values.ToArray());
|
||||||
|
|
||||||
if (id != null)
|
if (id != null)
|
||||||
AddReference(reader, id, createdObject);
|
AddReference(reader, id, createdObject);
|
||||||
@@ -1825,7 +1828,7 @@ To fix this error either change the environment to be fully trusted, change the
|
|||||||
if (objectContract.OverrideConstructor.GetParameters().Length > 0)
|
if (objectContract.OverrideConstructor.GetParameters().Length > 0)
|
||||||
{
|
{
|
||||||
createdFromNonDefaultConstructor = true;
|
createdFromNonDefaultConstructor = true;
|
||||||
return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.OverrideConstructor, id);
|
return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedCreator, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
newObject = objectContract.OverrideConstructor.Invoke(null);
|
newObject = objectContract.OverrideConstructor.Invoke(null);
|
||||||
@@ -1839,10 +1842,10 @@ To fix this error either change the environment to be fully trusted, change the
|
|||||||
// non-public and there is no other constructor
|
// non-public and there is no other constructor
|
||||||
newObject = objectContract.DefaultCreator();
|
newObject = objectContract.DefaultCreator();
|
||||||
}
|
}
|
||||||
else if (objectContract.ParametrizedConstructor != null)
|
else if (objectContract.ParametrizedCreator != null)
|
||||||
{
|
{
|
||||||
createdFromNonDefaultConstructor = true;
|
createdFromNonDefaultConstructor = true;
|
||||||
return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedConstructor, id);
|
return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedCreator, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newObject == null)
|
if (newObject == null)
|
||||||
|
|||||||
Reference in New Issue
Block a user