private static IDictionary CreateImmutableDictionaryFromTempValues(ref ReadStack state, JsonSerializerOptions options)
        {
            Debug.Assert(state.Current.IsProcessingImmutableDictionary);

            DefaultImmutableConverter converter = (DefaultImmutableConverter)state.Current.JsonPropertyInfo.EnumerableConverter;

            Debug.Assert(converter != null);

            return(converter.CreateFromDictionary(ref state, state.Current.TempDictionaryValues, options));
        }
示例#2
0
        // Creates an IEnumerable<TRuntimePropertyType> and populates it with the items in the
        // sourceList argument then uses the delegateKey argument to identify the appropriate cached
        // CreateRange<TRuntimePropertyType> method to create and return the desired immutable collection type.
        public override IDictionary CreateImmutableCollectionFromDictionary(Type collectionType, string delegateKey, IDictionary sourceDictionary, string propertyPath)
        {
            if (!DefaultImmutableConverter.TryGetCreateRangeDelegate(delegateKey, out object createRangeDelegateObj))
            {
                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(collectionType, propertyPath);
            }

            DefaultImmutableConverter.ImmutableDictCreateRangeDelegate <string, TRuntimeProperty> createRangeDelegate = (
                (DefaultImmutableConverter.ImmutableDictCreateRangeDelegate <string, TRuntimeProperty>)createRangeDelegateObj);

            return((IDictionary)createRangeDelegate.Invoke(CreateGenericIEnumerableFromDictionary(sourceDictionary)));
        }
示例#3
0
        internal static ClassType GetClassType(Type type)
        {
            Debug.Assert(type != null);

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                type = Nullable.GetUnderlyingType(type);
            }

            if (DefaultConverters.IsValueConvertable(type))
            {
                return(ClassType.Value);
            }

            if (DefaultImmutableConverter.TypeIsImmutableDictionary(type))
            {
                return(ClassType.ImmutableDictionary);
            }

            if (typeof(IDictionary).IsAssignableFrom(type) ||
                (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(IDictionary <,>) ||
                                        type.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary <,>))))
            {
                return(ClassType.Dictionary);
            }

            if (typeof(IEnumerable).IsAssignableFrom(type))
            {
                return(ClassType.Enumerable);
            }

            if (type == typeof(object))
            {
                return(ClassType.Unknown);
            }

            return(ClassType.Object);
        }
示例#4
0
        private void DetermineSerializationCapabilities()
        {
            if (ClassType != ClassType.Enumerable && ClassType != ClassType.Dictionary && ClassType != ClassType.ImmutableDictionary)
            {
                // We serialize if there is a getter + not ignoring readonly properties.
                ShouldSerialize = HasGetter && (HasSetter || !Options.IgnoreReadOnlyProperties);

                // We deserialize if there is a setter.
                ShouldDeserialize = HasSetter;
            }
            else
            {
                if (HasGetter)
                {
                    if (HasSetter)
                    {
                        ShouldDeserialize = true;
                    }
                    else if (!RuntimePropertyType.IsArray &&
                             (typeof(IList).IsAssignableFrom(RuntimePropertyType) || typeof(IDictionary).IsAssignableFrom(RuntimePropertyType)))
                    {
                        ShouldDeserialize = true;
                    }
                }
                //else if (HasSetter)
                //{
                //    // todo: Special case where there is no getter but a setter (and an EnumerableConverter)
                //}

                if (ShouldDeserialize)
                {
                    ShouldSerialize = HasGetter;

                    if (RuntimePropertyType.IsArray)
                    {
                        EnumerableConverter = s_jsonArrayConverter;
                    }
                    else if (ClassType == ClassType.ImmutableDictionary)
                    {
                        DefaultImmutableConverter.RegisterImmutableDictionary(
                            RuntimePropertyType, JsonClassInfo.GetElementType(RuntimePropertyType, parentType: null, memberInfo: null), Options);
                        EnumerableConverter = s_jsonImmutableConverter;
                    }
                    else if (typeof(IEnumerable).IsAssignableFrom(RuntimePropertyType))
                    {
                        Type elementType = JsonClassInfo.GetElementType(RuntimePropertyType, ParentClassType, PropertyInfo);

                        // If the property type only has interface(s) exposed by JsonEnumerableT<T> then use JsonEnumerableT as the converter.
                        if (RuntimePropertyType.IsAssignableFrom(typeof(JsonEnumerableT <>).MakeGenericType(elementType)))
                        {
                            EnumerableConverter = s_jsonEnumerableConverter;
                        }
                        // Else if IList can't be assigned from the property type (we populate and return an IList directly)
                        // and the type can be constructed with an IEnumerable<T>, then use the
                        // IEnumerableConstructible converter to create the instance.
                        else if (!typeof(IList).IsAssignableFrom(RuntimePropertyType) &&
                                 RuntimePropertyType.GetConstructor(new Type[] { typeof(List <>).MakeGenericType(elementType) }) != null)
                        {
                            EnumerableConverter = s_jsonIEnumerableConstuctibleConverter;
                        }
                        // Else if it's a System.Collections.Immutable type with one generic argument.
                        else if (RuntimePropertyType.IsGenericType &&
                                 RuntimePropertyType.FullName.StartsWith(DefaultImmutableConverter.ImmutableNamespace) &&
                                 RuntimePropertyType.GetGenericArguments().Length == 1)
                        {
                            DefaultImmutableConverter.RegisterImmutableCollection(RuntimePropertyType, elementType, Options);
                            EnumerableConverter = s_jsonImmutableConverter;
                        }
                    }
                }
                else
                {
                    ShouldSerialize = HasGetter && !Options.IgnoreReadOnlyProperties;
                }
            }
        }