in src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonArrayContract.cs [115:259]
public JsonArrayContract(Type underlyingType)
: base(underlyingType)
{
ContractType = JsonContractType.Array;
// netcoreapp3.0 uses EmptyPartition for empty enumerable. Treat as an empty array.
IsArray = CreatedType.IsArray ||
NonNullableUnderlyingType.IsGenericType()
&& NonNullableUnderlyingType.GetGenericTypeDefinition().FullName == "System.Linq.EmptyPartition`1";
bool canDeserialize;
Type? tempCollectionType;
if (IsArray)
{
CollectionItemType = ReflectionUtils.GetCollectionItemType(UnderlyingType);
IsReadOnlyOrFixedSize = true;
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
canDeserialize = true;
IsMultidimensionalArray = CreatedType.IsArray && UnderlyingType.GetArrayRank() > 1;
}
else if (typeof(IList).IsAssignableFrom(NonNullableUnderlyingType))
{
if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>),
out _genericCollectionDefinitionType))
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
else
CollectionItemType = ReflectionUtils.GetCollectionItemType(NonNullableUnderlyingType);
if (NonNullableUnderlyingType == typeof(IList)) CreatedType = typeof(List<object>);
if (CollectionItemType != null)
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType);
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyCollection<>));
canDeserialize = true;
}
else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>),
out _genericCollectionDefinitionType))
{
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>))
|| ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IList<>)))
CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
#if HAVE_ISET
if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ISet<>)))
{
CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType);
}
#endif
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType);
canDeserialize = true;
ShouldCreateWrapper = true;
}
#if HAVE_READ_ONLY_COLLECTIONS
else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>), out tempCollectionType))
{
CollectionItemType = tempCollectionType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>))
|| ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyList<>)))
{
CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType);
}
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, CollectionItemType);
#if HAVE_FSHARP_TYPES
StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType);
#endif
IsReadOnlyOrFixedSize = true;
canDeserialize = HasParameterizedCreatorInternal;
}
#endif
else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IEnumerable<>), out tempCollectionType))
{
CollectionItemType = tempCollectionType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IEnumerable<>)))
CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType);
#if HAVE_FSHARP_TYPES
StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType);
#endif
if (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
_genericCollectionDefinitionType = tempCollectionType;
IsReadOnlyOrFixedSize = false;
ShouldCreateWrapper = false;
canDeserialize = true;
}
else
{
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
IsReadOnlyOrFixedSize = true;
ShouldCreateWrapper = true;
canDeserialize = HasParameterizedCreatorInternal;
}
}
else
{
// types that implement IEnumerable and nothing else
canDeserialize = false;
ShouldCreateWrapper = true;
}
CanDeserialize = canDeserialize;
#if (NET20 || NET35)
if (CollectionItemType != null && ReflectionUtils.IsNullableType(CollectionItemType))
{
// bug in .NET 2.0 & 3.5 that List<Nullable<T>> throws an error when adding null via IList.Add(object)
// wrapper will handle calling Add(T) instead
if (ReflectionUtils.InheritsGenericDefinition(CreatedType, typeof(List<>), out tempCollectionType)
|| (IsArray && !IsMultidimensionalArray))
{
ShouldCreateWrapper = true;
}
}
#endif
if (CollectionItemType != null &&
ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(
NonNullableUnderlyingType,
CollectionItemType,
out var immutableCreatedType,
out var immutableParameterizedCreator))
{
CreatedType = immutableCreatedType;
_parameterizedCreator = immutableParameterizedCreator;
IsReadOnlyOrFixedSize = true;
CanDeserialize = true;
}
}