< Summary

Information
Line coverage
27%
Covered lines: 41
Uncovered lines: 109
Coverable lines: 150
Total lines: 221
Line coverage: 27.3%
Branch coverage
14%
Covered branches: 7
Total branches: 50
Branch coverage: 14%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
.ctor()100%11100%
CanConvert(...)100%11100%
CreateConverter(...)14%505025.87%

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Converters\Collection\IEnumerableConverterFactory.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections;
 5using System.Collections.Concurrent;
 6using System.Collections.Generic;
 7using System.Diagnostics;
 8using System.Diagnostics.CodeAnalysis;
 9using System.Reflection;
 10using System.Text.Json.Reflection;
 11using System.Text.Json.Serialization.Metadata;
 12
 13namespace System.Text.Json.Serialization.Converters
 14{
 15    /// <summary>
 16    /// Converter factory for all IEnumerable types.
 17    /// </summary>
 18    [RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
 19    internal sealed class IEnumerableConverterFactory : JsonConverterFactory
 20    {
 021        private static readonly IDictionaryConverter<IDictionary> s_converterForIDictionary = new IDictionaryConverter<I
 022        private static readonly IEnumerableConverter<IEnumerable> s_converterForIEnumerable = new IEnumerableConverter<I
 023        private static readonly IListConverter<IList> s_converterForIList = new IListConverter<IList>();
 24
 25        [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
 326        public IEnumerableConverterFactory() { }
 27
 28        public override bool CanConvert(Type typeToConvert)
 330329        {
 330330            return typeof(IEnumerable).IsAssignableFrom(typeToConvert);
 330331        }
 32
 33        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
 34            Justification = "The ctor is marked RequiresUnreferencedCode.")]
 35        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
 100236        {
 37            Type converterType;
 38            Type[] genericArgs;
 100239            Type? elementType = null;
 100240            Type? dictionaryKeyType = null;
 41            Type? actualTypeToConvert;
 42
 43            // Array
 100244            if (typeToConvert.IsArray)
 045            {
 46                // Verify that we don't have a multidimensional array.
 047                if (typeToConvert.GetArrayRank() > 1)
 048                {
 049                    return UnsupportedTypeConverterFactory.CreateUnsupportedConverterForType(typeToConvert);
 50                }
 51
 052                converterType = typeof(ArrayConverter<,>);
 053                elementType = typeToConvert.GetElementType();
 054            }
 55            // List<> or deriving from List<>
 100256            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericBaseClass(typeof(List<>))) != null)
 63857            {
 63858                converterType = typeof(ListOfTConverter<,>);
 63859                elementType = actualTypeToConvert.GetGenericArguments()[0];
 63860            }
 61            // Dictionary<TKey, TValue> or deriving from Dictionary<TKey, TValue>
 36462            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericBaseClass(typeof(Dictionary<,>))) != null)
 36463            {
 36464                genericArgs = actualTypeToConvert.GetGenericArguments();
 36465                converterType = typeof(DictionaryOfTKeyTValueConverter<,,>);
 36466                dictionaryKeyType = genericArgs[0];
 36467                elementType = genericArgs[1];
 36468            }
 69            // Immutable dictionaries from System.Collections.Immutable, e.g. ImmutableDictionary<TKey, TValue>
 070            else if (typeToConvert.IsImmutableDictionaryType())
 071            {
 072                genericArgs = typeToConvert.GetGenericArguments();
 073                converterType = typeof(ImmutableDictionaryOfTKeyTValueConverterWithReflection<,,>);
 074                dictionaryKeyType = genericArgs[0];
 075                elementType = genericArgs[1];
 076            }
 77            // IDictionary<TKey, TValue> or deriving from IDictionary<TKey, TValue>
 078            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(IDictionary<,>))) != null
 079            {
 080                genericArgs = actualTypeToConvert.GetGenericArguments();
 081                converterType = typeof(IDictionaryOfTKeyTValueConverter<,,>);
 082                dictionaryKeyType = genericArgs[0];
 083                elementType = genericArgs[1];
 084            }
 85            // IReadOnlyDictionary<TKey, TValue> or deriving from IReadOnlyDictionary<TKey, TValue>
 086            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(IReadOnlyDictionary<,>)))
 087            {
 088                genericArgs = actualTypeToConvert.GetGenericArguments();
 089                converterType = typeof(IReadOnlyDictionaryOfTKeyTValueConverter<,,>);
 090                dictionaryKeyType = genericArgs[0];
 091                elementType = genericArgs[1];
 092            }
 93            // Immutable non-dictionaries from System.Collections.Immutable, e.g. ImmutableStack<T>
 094            else if (typeToConvert.IsImmutableEnumerableType())
 095            {
 096                converterType = typeof(ImmutableEnumerableOfTConverterWithReflection<,>);
 097                elementType = typeToConvert.GetGenericArguments()[0];
 098            }
 99            // IList<>
 0100            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(IList<>))) != null)
 0101            {
 0102                converterType = typeof(IListOfTConverter<,>);
 0103                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0104            }
 105            // ISet<>
 0106            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(ISet<>))) != null)
 0107            {
 0108                converterType = typeof(ISetOfTConverter<,>);
 0109                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0110            }
 111#if NET
 112            // IReadOnlySet<>
 0113            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(IReadOnlySet<>))) != null
 0114            {
 0115                converterType = typeof(IReadOnlySetOfTConverter<,>);
 0116                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0117            }
 118#endif
 119            // ICollection<>
 0120            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(ICollection<>))) != null)
 0121            {
 0122                converterType = typeof(ICollectionOfTConverter<,>);
 0123                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0124            }
 125            // Stack<> or deriving from Stack<>
 0126            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericBaseClass(typeof(Stack<>))) != null)
 0127            {
 0128                converterType = typeof(StackOfTConverter<,>);
 0129                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0130            }
 131            // Queue<> or deriving from Queue<>
 0132            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericBaseClass(typeof(Queue<>))) != null)
 0133            {
 0134                converterType = typeof(QueueOfTConverter<,>);
 0135                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0136            }
 137            // ConcurrentStack<> or deriving from ConcurrentStack<>
 0138            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericBaseClass(typeof(ConcurrentStack<>))) != n
 0139            {
 0140                converterType = typeof(ConcurrentStackOfTConverter<,>);
 0141                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0142            }
 143            // ConcurrentQueue<> or deriving from ConcurrentQueue<>
 0144            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericBaseClass(typeof(ConcurrentQueue<>))) != n
 0145            {
 0146                converterType = typeof(ConcurrentQueueOfTConverter<,>);
 0147                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0148            }
 149            // IEnumerable<>, types assignable from List<>
 0150            else if ((actualTypeToConvert = typeToConvert.GetCompatibleGenericInterface(typeof(IEnumerable<>))) != null)
 0151            {
 0152                converterType = typeof(IEnumerableOfTConverter<,>);
 0153                elementType = actualTypeToConvert.GetGenericArguments()[0];
 0154            }
 155            // Check for non-generics after checking for generics.
 0156            else if (typeof(IDictionary).IsAssignableFrom(typeToConvert))
 0157            {
 0158                if (typeToConvert == typeof(IDictionary))
 0159                {
 0160                    return s_converterForIDictionary;
 161                }
 162
 0163                converterType = typeof(IDictionaryConverter<>);
 0164            }
 0165            else if (typeof(IList).IsAssignableFrom(typeToConvert))
 0166            {
 0167                if (typeToConvert == typeof(IList))
 0168                {
 0169                    return s_converterForIList;
 170                }
 171
 0172                converterType = typeof(IListConverter<>);
 0173            }
 0174            else if (typeToConvert.IsNonGenericStackOrQueue())
 0175            {
 0176                converterType = typeof(StackOrQueueConverterWithReflection<>);
 0177            }
 178            else
 0179            {
 0180                Debug.Assert(typeof(IEnumerable).IsAssignableFrom(typeToConvert));
 0181                if (typeToConvert == typeof(IEnumerable))
 0182                {
 0183                    return s_converterForIEnumerable;
 184                }
 185
 0186                converterType = typeof(IEnumerableConverter<>);
 0187            }
 188
 189            Type genericType;
 1002190            int numberOfGenericArgs = converterType.GetGenericArguments().Length;
 1002191            if (numberOfGenericArgs == 1)
 0192            {
 0193                genericType = converterType.MakeGenericType(typeToConvert);
 0194            }
 1002195            else if (numberOfGenericArgs == 2)
 638196            {
 638197                JsonTypeInfo.ValidateType(elementType!);
 198
 638199                genericType = converterType.MakeGenericType(typeToConvert, elementType!);
 638200            }
 201            else
 364202            {
 364203                Debug.Assert(numberOfGenericArgs == 3);
 204
 364205                JsonTypeInfo.ValidateType(elementType!);
 364206                JsonTypeInfo.ValidateType(dictionaryKeyType!);
 207
 364208                genericType = converterType.MakeGenericType(typeToConvert, dictionaryKeyType!, elementType!);
 364209            }
 210
 1002211            JsonConverter converter = (JsonConverter)Activator.CreateInstance(
 1002212                genericType,
 1002213                BindingFlags.Instance | BindingFlags.Public,
 1002214                binder: null,
 1002215                args: null,
 1002216                culture: null)!;
 217
 1002218            return converter;
 1002219        }
 220    }
 221}