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 JsonDictionaryContract : JsonContainerContract
{
private readonly Type _genericCollectionDefinitionType;
private Type _genericWrapperType;
private ObjectConstructor _genericWrapperCreator;
private Func _genericTemporaryDictionaryCreator;
private readonly ConstructorInfo _parameterizedConstructor;
private ObjectConstructor _overrideCreator;
private ObjectConstructor _parameterizedCreator;
///
/// Gets or sets the property name resolver.
///
/// The property name resolver.
[Obsolete("PropertyNameResolver is obsolete. Use DictionaryKeyResolver instead.")]
public Func PropertyNameResolver
{
get
{
return DictionaryKeyResolver;
}
set
{
DictionaryKeyResolver = value;
}
}
///
/// Gets or sets the dictionary key resolver.
///
/// The dictionary key resolver.
public Func DictionaryKeyResolver { get; set; }
///
/// Gets the of the dictionary keys.
///
/// The of the dictionary keys.
public Type DictionaryKeyType { get; private set; }
///
/// Gets the of the dictionary values.
///
/// The of the dictionary values.
public Type DictionaryValueType { get; private set; }
internal JsonContract KeyContract { get; set; }
internal bool ShouldCreateWrapper { 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;
}
}
///
/// Gets a value indicating whether the creator has a parameter with the dictionary values.
///
/// true if the creator has a parameter with the dictionary 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 JsonDictionaryContract(Type underlyingType)
: base(underlyingType)
{
ContractType = JsonContractType.Dictionary;
Type keyType;
Type valueType;
if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IDictionary<, >), out _genericCollectionDefinitionType))
{
keyType = _genericCollectionDefinitionType.GetGenericArguments()[0];
valueType = _genericCollectionDefinitionType.GetGenericArguments()[1];
if (ReflectionUtils.IsGenericDefinition(base.UnderlyingType, typeof(IDictionary<, >)))
{
base.CreatedType = typeof(Dictionary<, >).MakeGenericType(keyType, valueType);
}
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyDictionary<, >));
}
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyDictionary<, >), out _genericCollectionDefinitionType))
{
keyType = _genericCollectionDefinitionType.GetGenericArguments()[0];
valueType = _genericCollectionDefinitionType.GetGenericArguments()[1];
if (ReflectionUtils.IsGenericDefinition(base.UnderlyingType, typeof(IReadOnlyDictionary<, >)))
{
base.CreatedType = typeof(ReadOnlyDictionary<, >).MakeGenericType(keyType, valueType);
}
IsReadOnlyOrFixedSize = true;
}
else
{
ReflectionUtils.GetDictionaryKeyValueTypes(base.UnderlyingType, out keyType, out valueType);
if (base.UnderlyingType == typeof(IDictionary))
{
base.CreatedType = typeof(Dictionary);
}
}
if (keyType != null && valueType != null)
{
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(base.CreatedType, typeof(KeyValuePair<, >).MakeGenericType(keyType, valueType), typeof(IDictionary<, >).MakeGenericType(keyType, valueType));
if (!HasParameterizedCreatorInternal && underlyingType.Name == "FSharpMap`2")
{
FSharpUtils.EnsureInitialized(underlyingType.Assembly());
_parameterizedCreator = FSharpUtils.CreateMap(keyType, valueType);
}
}
ShouldCreateWrapper = !typeof(IDictionary).IsAssignableFrom(base.CreatedType);
DictionaryKeyType = keyType;
DictionaryValueType = valueType;
if (ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract(underlyingType, DictionaryKeyType, DictionaryValueType, out var createdType, out var parameterizedCreator))
{
base.CreatedType = createdType;
_parameterizedCreator = parameterizedCreator;
IsReadOnlyOrFixedSize = true;
}
}
internal IWrappedDictionary CreateWrapper(object dictionary)
{
if (_genericWrapperCreator == null)
{
_genericWrapperType = typeof(DictionaryWrapper<, >).MakeGenericType(DictionaryKeyType, DictionaryValueType);
ConstructorInfo constructor = _genericWrapperType.GetConstructor(new Type[1] { _genericCollectionDefinitionType });
_genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor);
}
return (IWrappedDictionary)_genericWrapperCreator(dictionary);
}
internal IDictionary CreateTemporaryDictionary()
{
if (_genericTemporaryDictionaryCreator == null)
{
Type type = typeof(Dictionary<, >).MakeGenericType(DictionaryKeyType ?? typeof(object), DictionaryValueType ?? typeof(object));
_genericTemporaryDictionaryCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type);
}
return (IDictionary)_genericTemporaryDictionaryCreator();
}
}
}