// This method gets the runtime information for a given type or property. // The runtime information consists of the following: // - class type, // - runtime type, // - element type (if the type is a collection), // - the converter (either native or custom), if one exists. public static JsonConverter GetConverter( Type type, Type?parentClassType, PropertyInfo?propertyInfo, out Type runtimeType, JsonSerializerOptions options) { Debug.Assert(type != null); ValidateType(type, parentClassType, propertyInfo, options); JsonConverter converter = options.DetermineConverter(parentClassType, type, propertyInfo) !; // The runtimeType is the actual value being assigned to the property. // There are three types to consider for the runtimeType: // 1) The declared type (the actual property type). // 2) The converter.TypeToConvert (the T value that the converter supports). // 3) The converter.RuntimeType (used with interfaces such as IList). Type converterRuntimeType = converter.RuntimeType; if (type == converterRuntimeType) { runtimeType = type; } else { if (type.IsInterface) { runtimeType = converterRuntimeType; } else if (converterRuntimeType.IsInterface) { runtimeType = type; } else { // Use the most derived version from the converter.RuntimeType or converter.TypeToConvert. if (type.IsAssignableFrom(converterRuntimeType)) { runtimeType = converterRuntimeType; } else if (converterRuntimeType.IsAssignableFrom(type) || converter.TypeToConvert.IsAssignableFrom(type)) { runtimeType = type; } else { runtimeType = default !;