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(); } } }