-Added support for falling back to IEnumerable<T> constructor on lists
-Added support for falling back to IEnumerable<KeyValuePair<TKey, TValue>> constructor on dictionaries
This commit is contained in:
@@ -2723,14 +2723,23 @@ Path '', line 1, position 2.",
|
||||
[Test]
|
||||
public void DeserializeDictionaryWithNoDefaultConstructor()
|
||||
{
|
||||
string json = "{key1:'value',key2:'value',key3:'value'}";
|
||||
string json = "{key1:'value1',key2:'value2',key3:'value3'}";
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(
|
||||
"Unable to find a default constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+DictionaryWithNoDefaultConstructor. Path 'key1', line 1, position 6.",
|
||||
() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<DictionaryWithNoDefaultConstructor>(json);
|
||||
});
|
||||
var dic = JsonConvert.DeserializeObject<DictionaryWithNoDefaultConstructor>(json);
|
||||
|
||||
Assert.AreEqual(3, dic.Count);
|
||||
Assert.AreEqual("value1", dic["key1"]);
|
||||
Assert.AreEqual("value2", dic["key2"]);
|
||||
Assert.AreEqual("value3", dic["key3"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDictionaryWithNoDefaultConstructor_PreserveReferences()
|
||||
{
|
||||
string json = "{'$id':'1',key1:'value1',key2:'value2',key3:'value3'}";
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>("Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+DictionaryWithNoDefaultConstructor. Path 'key1', line 1, position 16.",
|
||||
() => JsonConvert.DeserializeObject<DictionaryWithNoDefaultConstructor>(json, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All }));
|
||||
}
|
||||
|
||||
public class DictionaryWithNoDefaultConstructor : Dictionary<string, string>
|
||||
@@ -7941,6 +7950,53 @@ Parameter name: value",
|
||||
]", json);
|
||||
}
|
||||
#endif
|
||||
|
||||
public class PrivateDefaultCtorList<T> : List<T>
|
||||
{
|
||||
private PrivateDefaultCtorList()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializePrivateListCtor()
|
||||
{
|
||||
ExceptionAssert.Throws<JsonSerializationException>(
|
||||
"Unable to find a constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+PrivateDefaultCtorList`1[System.Int32]. Path '', line 1, position 1.",
|
||||
() => JsonConvert.DeserializeObject<PrivateDefaultCtorList<int>>("[1,2]")
|
||||
);
|
||||
|
||||
var list = JsonConvert.DeserializeObject<PrivateDefaultCtorList<int>>("[1,2]", new JsonSerializerSettings
|
||||
{
|
||||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
||||
});
|
||||
|
||||
Assert.AreEqual(2, list.Count);
|
||||
}
|
||||
|
||||
public class PrivateDefaultCtorWithIEnumerableCtorList<T> : List<T>
|
||||
{
|
||||
private PrivateDefaultCtorWithIEnumerableCtorList()
|
||||
{
|
||||
}
|
||||
|
||||
public PrivateDefaultCtorWithIEnumerableCtorList(IEnumerable<T> values)
|
||||
: base(values)
|
||||
{
|
||||
Add(default(T));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializePrivateListConstructor()
|
||||
{
|
||||
var list = JsonConvert.DeserializeObject<PrivateDefaultCtorWithIEnumerableCtorList<int>>("[1,2]");
|
||||
|
||||
Assert.AreEqual(3, list.Count);
|
||||
Assert.AreEqual(1, list[0]);
|
||||
Assert.AreEqual(2, list[1]);
|
||||
Assert.AreEqual(0, list[2]);
|
||||
}
|
||||
}
|
||||
|
||||
public enum Antworten
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
}";
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(
|
||||
@"Cannot preserve reference to array or readonly list: System.String[][]. Path '$values', line 3, position 15.",
|
||||
@"Cannot preserve reference to array or readonly list, or list created from a non-default constructor: System.String[][]. Path '$values', line 3, position 15.",
|
||||
() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<string[][]>(json,
|
||||
|
||||
@@ -65,26 +65,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
internal bool ShouldCreateWrapper { get; private set; }
|
||||
internal bool CanDeserialize { get; private set; }
|
||||
internal Type TemporaryCollectionType { get; private set; }
|
||||
internal bool IsReadOnlyOrFixedSize { get; private set; }
|
||||
|
||||
private ConstructorInfo ResolveReadOnlyCollectionConstructor(Type readOnlyCollectionType, Type collectionTypeType)
|
||||
{
|
||||
Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable<>), collectionTypeType);
|
||||
|
||||
foreach (ConstructorInfo constructor in readOnlyCollectionType.GetConstructors())
|
||||
{
|
||||
IList<ParameterInfo> parameters = constructor.GetParameters();
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
|
||||
return constructor;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
internal ConstructorInfo ParametrizedConstructor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonArrayContract"/> class.
|
||||
@@ -104,15 +86,16 @@ namespace Newtonsoft.Json.Serialization
|
||||
IsReadOnlyOrFixedSize = true;
|
||||
|
||||
canDeserialize = true;
|
||||
TemporaryCollectionType = typeof (List<object>);
|
||||
IsMultidimensionalArray = (UnderlyingType.IsArray && UnderlyingType.GetArrayRank() > 1);
|
||||
}
|
||||
else if (ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>), out tempCollectionType))
|
||||
{
|
||||
CollectionItemType = tempCollectionType.GetGenericArguments()[0];
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||
|
||||
IsReadOnlyOrFixedSize = true;
|
||||
|
||||
canDeserialize = (ResolveReadOnlyCollectionConstructor(underlyingType, CollectionItemType) != null);
|
||||
TemporaryCollectionType = ReflectionUtils.MakeGenericType(typeof(List<>), CollectionItemType);
|
||||
canDeserialize = (ParametrizedConstructor != null);
|
||||
}
|
||||
else if (typeof(IList).IsAssignableFrom(underlyingType))
|
||||
{
|
||||
@@ -121,11 +104,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
else
|
||||
CollectionItemType = ReflectionUtils.GetCollectionItemType(underlyingType);
|
||||
|
||||
if (CollectionItemType != null)
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||
canDeserialize = true;
|
||||
}
|
||||
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
|
||||
{
|
||||
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||
canDeserialize = true;
|
||||
ShouldCreateWrapper = true;
|
||||
}
|
||||
@@ -133,8 +119,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof (IReadOnlyCollection<>), out tempCollectionType))
|
||||
{
|
||||
CollectionItemType = underlyingType.GetGenericArguments()[0];
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||
IsReadOnlyOrFixedSize = true;
|
||||
TemporaryCollectionType = ReflectionUtils.MakeGenericType(typeof(List<>), CollectionItemType);
|
||||
ShouldCreateWrapper = !typeof(IList).IsAssignableFrom(underlyingType);
|
||||
|
||||
canDeserialize = (ResolveReadOnlyCollectionConstructor(underlyingType, CollectionItemType) != null
|
||||
@@ -145,6 +131,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof (IEnumerable<>), out tempCollectionType))
|
||||
{
|
||||
CollectionItemType = tempCollectionType.GetGenericArguments()[0];
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||
|
||||
if (underlyingType.GetGenericTypeDefinition() == typeof (IEnumerable<>))
|
||||
{
|
||||
@@ -158,8 +145,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
IsReadOnlyOrFixedSize = true;
|
||||
ShouldCreateWrapper = true;
|
||||
canDeserialize = (ResolveReadOnlyCollectionConstructor(underlyingType, CollectionItemType) != null);
|
||||
TemporaryCollectionType = ReflectionUtils.MakeGenericType(typeof(List<>), CollectionItemType);
|
||||
canDeserialize = (ParametrizedConstructor != null);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -195,8 +181,6 @@ namespace Newtonsoft.Json.Serialization
|
||||
ShouldCreateWrapper = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
IsMultidimensionalArray = (UnderlyingType.IsArray && UnderlyingType.GetArrayRank() > 1);
|
||||
}
|
||||
|
||||
internal IWrappedCollection CreateWrapper(object list)
|
||||
@@ -232,7 +216,12 @@ namespace Newtonsoft.Json.Serialization
|
||||
internal IList CreateTemporaryCollection()
|
||||
{
|
||||
if (_genericTemporaryCollectionCreator == null)
|
||||
_genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(TemporaryCollectionType);
|
||||
{
|
||||
// multidimensional array will also have array instances in it
|
||||
Type collectionItemType = (IsMultidimensionalArray) ? typeof (object) : CollectionItemType;
|
||||
Type temporaryListType = ReflectionUtils.MakeGenericType(typeof(List<>), collectionItemType);
|
||||
_genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(temporaryListType);
|
||||
}
|
||||
|
||||
return (IList)_genericTemporaryCollectionCreator();
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
internal bool ShouldCreateWrapper { get; private set; }
|
||||
internal bool IsReadOnlyOrFixedSize { get; private set; }
|
||||
internal ConstructorInfo ParametrizedConstructor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonDictionaryContract"/> class.
|
||||
@@ -101,6 +102,9 @@ namespace Newtonsoft.Json.Serialization
|
||||
ReflectionUtils.GetDictionaryKeyValueTypes(UnderlyingType, out keyType, out valueType);
|
||||
}
|
||||
|
||||
if (keyType != null && valueType != null)
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, ReflectionUtils.MakeGenericType(typeof(KeyValuePair<,>), keyType, valueType));
|
||||
|
||||
ShouldCreateWrapper = !typeof (IDictionary).IsAssignableFrom(underlyingType);
|
||||
|
||||
DictionaryKeyType = keyType;
|
||||
|
||||
@@ -369,53 +369,80 @@ namespace Newtonsoft.Json.Serialization
|
||||
switch (contract.ContractType)
|
||||
{
|
||||
case JsonContractType.Object:
|
||||
bool createdFromNonDefaultConstructor = false;
|
||||
JsonObjectContract objectContract = (JsonObjectContract) contract;
|
||||
object targetObject;
|
||||
if (existingValue != null)
|
||||
targetObject = existingValue;
|
||||
else
|
||||
targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultConstructor);
|
||||
{
|
||||
bool createdFromNonDefaultConstructor = false;
|
||||
JsonObjectContract objectContract = (JsonObjectContract) contract;
|
||||
object targetObject;
|
||||
if (existingValue != null)
|
||||
targetObject = existingValue;
|
||||
else
|
||||
targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultConstructor);
|
||||
|
||||
// don't populate if read from non-default constructor because the object has already been read
|
||||
if (createdFromNonDefaultConstructor)
|
||||
return targetObject;
|
||||
// don't populate if read from non-default constructor because the object has already been read
|
||||
if (createdFromNonDefaultConstructor)
|
||||
return targetObject;
|
||||
|
||||
return PopulateObject(targetObject, reader, objectContract, member, id);
|
||||
return PopulateObject(targetObject, reader, objectContract, member, id);
|
||||
}
|
||||
case JsonContractType.Primitive:
|
||||
JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
|
||||
// if the content is inside $value then read past it
|
||||
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
|
||||
{
|
||||
CheckedRead(reader);
|
||||
JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract) contract;
|
||||
// if the content is inside $value then read past it
|
||||
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
|
||||
{
|
||||
CheckedRead(reader);
|
||||
|
||||
// the token should not be an object because the $type value could have been included in the object
|
||||
// without needing the $value property
|
||||
if (reader.TokenType == JsonToken.StartObject)
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType);
|
||||
// the token should not be an object because the $type value could have been included in the object
|
||||
// without needing the $value property
|
||||
if (reader.TokenType == JsonToken.StartObject)
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType);
|
||||
|
||||
object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, null, existingValue);
|
||||
object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, null, existingValue);
|
||||
|
||||
CheckedRead(reader);
|
||||
return value;
|
||||
CheckedRead(reader);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case JsonContractType.Dictionary:
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract;
|
||||
object targetDictionary;
|
||||
if (existingValue != null)
|
||||
targetDictionary = dictionaryContract.ShouldCreateWrapper ? dictionaryContract.CreateWrapper(existingValue) : existingValue;
|
||||
else
|
||||
targetDictionary = CreateNewDictionary(reader, dictionaryContract);
|
||||
|
||||
object dictionary = PopulateDictionary((IDictionary) targetDictionary, reader, dictionaryContract, member, id);
|
||||
|
||||
if (dictionaryContract.IsReadOnlyOrFixedSize)
|
||||
{
|
||||
dictionary = ReflectionUtils.CreateInstance(contract.CreatedType, dictionary);
|
||||
}
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract;
|
||||
object targetDictionary;
|
||||
|
||||
return dictionary;
|
||||
if (existingValue == null)
|
||||
{
|
||||
bool createdFromNonDefaultConstructor;
|
||||
IDictionary dictionary = CreateNewDictionary(reader, dictionaryContract, out createdFromNonDefaultConstructor);
|
||||
|
||||
if (id != null && createdFromNonDefaultConstructor)
|
||||
throw JsonSerializationException.Create(reader, "Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
if (contract.OnSerializingCallbacks.Count > 0 && createdFromNonDefaultConstructor)
|
||||
throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
if (contract.OnErrorCallbacks.Count > 0 && createdFromNonDefaultConstructor)
|
||||
throw JsonSerializationException.Create(reader, "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
PopulateDictionary(dictionary, reader, dictionaryContract, member, id);
|
||||
|
||||
if (createdFromNonDefaultConstructor)
|
||||
{
|
||||
return dictionaryContract.ParametrizedConstructor.Invoke(new object[] {dictionary});
|
||||
}
|
||||
else if (dictionary is IWrappedDictionary)
|
||||
{
|
||||
return ((IWrappedDictionary)dictionary).UnderlyingDictionary;
|
||||
}
|
||||
|
||||
targetDictionary = dictionary;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetDictionary = PopulateDictionary(dictionaryContract.ShouldCreateWrapper ? dictionaryContract.CreateWrapper(existingValue) : (IDictionary) existingValue, reader, dictionaryContract, member, id);
|
||||
}
|
||||
|
||||
return targetDictionary;
|
||||
}
|
||||
#if !(NET35 || NET20)
|
||||
case JsonContractType.Dynamic:
|
||||
JsonDynamicContract dynamicContract = (JsonDynamicContract) contract;
|
||||
@@ -584,25 +611,24 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
|
||||
if (existingValue == null)
|
||||
{
|
||||
if (id != null && arrayContract.IsReadOnlyOrFixedSize)
|
||||
throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
bool createdFromNonDefaultConstructor;
|
||||
IList list = CreateNewList(reader, arrayContract, out createdFromNonDefaultConstructor);
|
||||
|
||||
if (contract.OnSerializingCallbacks.Count > 0 && arrayContract.IsReadOnlyOrFixedSize)
|
||||
throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
if (id != null && createdFromNonDefaultConstructor)
|
||||
throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
if (contract.OnErrorCallbacks.Count > 0 && arrayContract.IsReadOnlyOrFixedSize)
|
||||
throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
if (contract.OnSerializingCallbacks.Count > 0 && createdFromNonDefaultConstructor)
|
||||
throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
IList list = CreateNewList(reader, arrayContract);
|
||||
if (contract.OnErrorCallbacks.Count > 0 && createdFromNonDefaultConstructor)
|
||||
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.IsMultidimensionalArray)
|
||||
PopulateList(list, reader, arrayContract, member, id);
|
||||
else
|
||||
PopulateMultidimensionalArray(list, reader, arrayContract, member, id);
|
||||
|
||||
// create readonly and fixed sized collections using the temporary list
|
||||
// not needed for IEnumerable<T> properties. temp list is final
|
||||
if (arrayContract.IsReadOnlyOrFixedSize && list.GetType() != contract.CreatedType)
|
||||
if (createdFromNonDefaultConstructor)
|
||||
{
|
||||
if (arrayContract.IsMultidimensionalArray)
|
||||
{
|
||||
@@ -610,11 +636,14 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
}
|
||||
else if (contract.CreatedType.IsArray)
|
||||
{
|
||||
list = CollectionUtils.ToArray(((List<object>)list).ToArray(), arrayContract.CollectionItemType);
|
||||
Array a = Array.CreateInstance(arrayContract.CollectionItemType, list.Count);
|
||||
list.CopyTo(a, 0);
|
||||
list = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReflectionUtils.CreateInstance(contract.CreatedType, list);
|
||||
// call constructor that takes IEnumerable<T>
|
||||
return arrayContract.ParametrizedConstructor.Invoke(new object[] { list });
|
||||
}
|
||||
}
|
||||
else if (list is IWrappedCollection)
|
||||
@@ -837,47 +866,64 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
return true;
|
||||
}
|
||||
|
||||
private IList CreateNewList(JsonReader reader, JsonArrayContract contract)
|
||||
private IList CreateNewList(JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultConstructor)
|
||||
{
|
||||
// some types like non-generic IEnumerable can be serialized but not deserialized
|
||||
if (!contract.CanDeserialize)
|
||||
throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType));
|
||||
|
||||
if (contract.IsReadOnlyOrFixedSize && contract.TemporaryCollectionType != null)
|
||||
if (contract.IsReadOnlyOrFixedSize)
|
||||
{
|
||||
createdFromNonDefaultConstructor = true;
|
||||
return contract.CreateTemporaryCollection();
|
||||
}
|
||||
else
|
||||
else if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
|
||||
{
|
||||
object list = contract.DefaultCreator();
|
||||
|
||||
if (contract.ShouldCreateWrapper)
|
||||
list = contract.CreateWrapper(list);
|
||||
|
||||
createdFromNonDefaultConstructor = false;
|
||||
return (IList)list;
|
||||
}
|
||||
else if (contract.ParametrizedConstructor != null)
|
||||
{
|
||||
createdFromNonDefaultConstructor = true;
|
||||
return contract.CreateTemporaryCollection();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
}
|
||||
}
|
||||
|
||||
private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract)
|
||||
private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract, out bool createdFromNonDefaultConstructor)
|
||||
{
|
||||
object dictionary;
|
||||
|
||||
if (contract.IsReadOnlyOrFixedSize)
|
||||
{
|
||||
dictionary = contract.CreateTemporaryDictionary();
|
||||
createdFromNonDefaultConstructor = true;
|
||||
return contract.CreateTemporaryDictionary();
|
||||
}
|
||||
else if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
|
||||
{
|
||||
dictionary = contract.DefaultCreator();
|
||||
object dictionary = contract.DefaultCreator();
|
||||
|
||||
if (contract.ShouldCreateWrapper)
|
||||
dictionary = contract.CreateWrapper(dictionary);
|
||||
|
||||
createdFromNonDefaultConstructor = false;
|
||||
return (IDictionary) dictionary;
|
||||
}
|
||||
else if (contract.ParametrizedConstructor != null)
|
||||
{
|
||||
createdFromNonDefaultConstructor = true;
|
||||
return contract.CreateTemporaryDictionary();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
}
|
||||
|
||||
return (IDictionary)dictionary;
|
||||
}
|
||||
|
||||
private void OnDeserializing(JsonReader reader, JsonContract contract, object value)
|
||||
|
||||
@@ -114,6 +114,24 @@ namespace Newtonsoft.Json.Utilities
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ConstructorInfo ResolveEnumableCollectionConstructor(Type collectionType, Type collectionItemType)
|
||||
{
|
||||
Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable<>), collectionItemType);
|
||||
|
||||
foreach (ConstructorInfo constructor in collectionType.GetConstructors(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
IList<ParameterInfo> parameters = constructor.GetParameters();
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
|
||||
return constructor;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IWrappedCollection CreateCollectionWrapper(object list)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(list, "list");
|
||||
|
||||
Reference in New Issue
Block a user