private JsonPropertyInfo AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options) { JsonPropertyInfo jsonInfo = CreateProperty(propertyType, propertyType, propertyInfo, classType, options); // Convert non-immutable dictionary interfaces to concrete types. if (propertyType.IsInterface && jsonInfo.ClassType == ClassType.Dictionary) { JsonClassInfo elementClassInfo = jsonInfo.ElementClassInfo; JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options); Type newPropertyType = elementPropertyInfo.GetDictionaryConcreteType(); if (propertyType != newPropertyType) { jsonInfo = CreateProperty(propertyType, newPropertyType, propertyInfo, classType, options); } } else if (jsonInfo.ClassType == ClassType.Enumerable && !propertyType.IsArray && (IsDeserializedByAssigningFromList(propertyType) || IsSetInterface(propertyType))) { JsonClassInfo elementClassInfo = jsonInfo.ElementClassInfo; JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options); // Get a runtime type for the property. e.g. ISet<T> -> HashSet<T>, ICollection -> List<object> // We use the element's JsonPropertyInfo so we can utilize the generic support. Type newPropertyType = elementPropertyInfo.GetConcreteType(propertyType); if ((propertyType != newPropertyType) && propertyType.IsAssignableFrom(newPropertyType)) { jsonInfo = CreateProperty(propertyType, newPropertyType, propertyInfo, classType, options); } } return(jsonInfo); }
private JsonPropertyInfo AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options) { JsonPropertyInfo jsonInfo; // Get implemented type, if applicable. // Will return the propertyType itself if it's a non-enumerable, string, or natively supported collection. Type implementedType = GetImplementedCollectionType(propertyType); if (implementedType != propertyType) { jsonInfo = CreateProperty(implementedType, implementedType, implementedType, null, typeof(object), options); } else { jsonInfo = CreateProperty(propertyType, propertyType, propertyType, propertyInfo, classType, options); } // Convert non-immutable dictionary interfaces to concrete types. if (IsNativelySupportedCollection(propertyType) && implementedType.IsInterface && jsonInfo.ClassType == ClassType.Dictionary) { JsonClassInfo elementClassInfo = jsonInfo.ElementClassInfo; JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options); Type newPropertyType = elementPropertyInfo.GetDictionaryConcreteType(); if (implementedType != newPropertyType) { jsonInfo = CreateProperty(propertyType, newPropertyType, implementedType, propertyInfo, classType, options); } else { jsonInfo = CreateProperty(propertyType, implementedType, implementedType, propertyInfo, classType, options); } } else if (jsonInfo.ClassType == ClassType.Enumerable && !implementedType.IsArray && ((IsDeserializedByAssigningFromList(implementedType) && IsNativelySupportedCollection(propertyType)) || IsSetInterface(implementedType))) { JsonClassInfo elementClassInfo = jsonInfo.ElementClassInfo; JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options); // Get a runtime type for the implemented property. e.g. ISet<T> -> HashSet<T>, ICollection -> List<object> // We use the element's JsonPropertyInfo so we can utilize the generic support. Type newPropertyType = elementPropertyInfo.GetConcreteType(implementedType); if ((implementedType != newPropertyType) && implementedType.IsAssignableFrom(newPropertyType)) { jsonInfo = CreateProperty(propertyType, newPropertyType, implementedType, propertyInfo, classType, options); } else { jsonInfo = CreateProperty(propertyType, implementedType, implementedType, propertyInfo, classType, options); } } else if (propertyType != implementedType) { jsonInfo = CreateProperty(propertyType, implementedType, implementedType, propertyInfo, classType, options); } return(jsonInfo); }