using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using DPumpHydr.WinFrmUI.WenSkin.Json.Utilities;
namespace DPumpHydr.WinFrmUI.WenSkin.Json.Serialization
{
///
/// Contract details for a used by the .
///
public class JsonArrayContract : JsonContainerContract
{
private readonly Type _genericCollectionDefinitionType;
private Type _genericWrapperType;
private ObjectConstructor _genericWrapperCreator;
private Func _genericTemporaryCollectionCreator;
private readonly ConstructorInfo _parameterizedConstructor;
private ObjectConstructor _parameterizedCreator;
private ObjectConstructor _overrideCreator;
///
/// Gets the of the collection items.
///
/// The of the collection items.
public Type CollectionItemType { get; private set; }
///
/// Gets a value indicating whether the collection type is a multidimensional array.
///
/// true if the collection type is a multidimensional array; otherwise, false .
public bool IsMultidimensionalArray { get; private set; }
internal bool IsArray { get; private set; }
internal bool ShouldCreateWrapper { get; private set; }
internal bool CanDeserialize { get; private set; }
internal ObjectConstructor ParameterizedCreator
{
get
{
if (_parameterizedCreator == null)
{
_parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor);
}
return _parameterizedCreator;
}
}
///
/// Gets or sets the function used to create the object. When set this function will override .
///
/// The function used to create the object.
public ObjectConstructor OverrideCreator
{
get
{
return _overrideCreator;
}
set
{
_overrideCreator = value;
CanDeserialize = true;
}
}
///
/// Gets a value indicating whether the creator has a parameter with the collection values.
///
/// true if the creator has a parameter with the collection values; otherwise, false .
public bool HasParameterizedCreator { get; set; }
internal bool HasParameterizedCreatorInternal
{
get
{
if (!HasParameterizedCreator && _parameterizedCreator == null)
{
return _parameterizedConstructor != null;
}
return true;
}
}
///
/// Initializes a new instance of the class.
///
/// The underlying type for the contract.
public JsonArrayContract(Type underlyingType)
: base(underlyingType)
{
ContractType = JsonContractType.Array;
IsArray = base.CreatedType.IsArray;
bool canDeserialize;
Type implementingType;
if (IsArray)
{
CollectionItemType = ReflectionUtils.GetCollectionItemType(base.UnderlyingType);
IsReadOnlyOrFixedSize = true;
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
canDeserialize = true;
IsMultidimensionalArray = IsArray && base.UnderlyingType.GetArrayRank() > 1;
}
else if (typeof(IList).IsAssignableFrom(underlyingType))
{
if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
{
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
}
else
{
CollectionItemType = ReflectionUtils.GetCollectionItemType(underlyingType);
}
if (underlyingType == typeof(IList))
{
base.CreatedType = typeof(List);
}
if (CollectionItemType != null)
{
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType);
}
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>));
canDeserialize = true;
}
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
{
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(ICollection<>)) || ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IList<>)))
{
base.CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
}
if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(ISet<>)))
{
base.CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType);
}
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType);
canDeserialize = true;
ShouldCreateWrapper = true;
}
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyCollection<>), out implementingType))
{
CollectionItemType = implementingType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IReadOnlyCollection<>)) || ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IReadOnlyList<>)))
{
base.CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType);
}
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(base.CreatedType, CollectionItemType);
IsReadOnlyOrFixedSize = true;
canDeserialize = HasParameterizedCreatorInternal;
}
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IEnumerable<>), out implementingType))
{
CollectionItemType = implementingType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(base.UnderlyingType, typeof(IEnumerable<>)))
{
base.CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
}
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType);
if (!HasParameterizedCreatorInternal && underlyingType.Name == "FSharpList`1")
{
FSharpUtils.EnsureInitialized(underlyingType.Assembly());
_parameterizedCreator = FSharpUtils.CreateSeq(CollectionItemType);
}
if (underlyingType.IsGenericType() && underlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
_genericCollectionDefinitionType = implementingType;
IsReadOnlyOrFixedSize = false;
ShouldCreateWrapper = false;
canDeserialize = true;
}
else
{
_genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
IsReadOnlyOrFixedSize = true;
ShouldCreateWrapper = true;
canDeserialize = HasParameterizedCreatorInternal;
}
}
else
{
canDeserialize = false;
ShouldCreateWrapper = true;
}
CanDeserialize = canDeserialize;
if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(underlyingType, CollectionItemType, out var createdType, out var parameterizedCreator))
{
base.CreatedType = createdType;
_parameterizedCreator = parameterizedCreator;
IsReadOnlyOrFixedSize = true;
CanDeserialize = true;
}
}
internal IWrappedCollection CreateWrapper(object list)
{
if (_genericWrapperCreator == null)
{
_genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType);
Type type = ((!ReflectionUtils.InheritsGenericDefinition(_genericCollectionDefinitionType, typeof(List<>)) && !(_genericCollectionDefinitionType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) ? _genericCollectionDefinitionType : typeof(ICollection<>).MakeGenericType(CollectionItemType));
ConstructorInfo constructor = _genericWrapperType.GetConstructor(new Type[1] { type });
_genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor);
}
return (IWrappedCollection)_genericWrapperCreator(list);
}
internal IList CreateTemporaryCollection()
{
if (_genericTemporaryCollectionCreator == null)
{
Type type = ((IsMultidimensionalArray || CollectionItemType == null) ? typeof(object) : CollectionItemType);
Type type2 = typeof(List<>).MakeGenericType(type);
_genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type2);
}
return (IList)_genericTemporaryCollectionCreator();
}
}
}