< Summary

Information
Class: System.Text.Json.Serialization.Converters.ObjectConverterFactory
Assembly: System.Text.Json
File(s): D:\runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Converters\Object\ObjectConverterFactory.cs
Line coverage
53%
Covered lines: 39
Uncovered lines: 34
Coverable lines: 73
Total lines: 137
Line coverage: 53.4%
Branch coverage
42%
Covered branches: 12
Total branches: 28
Branch coverage: 42.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
CanConvert(...)100%11100%
CreateConverter(...)42.85%282847.69%

File(s)

D:\runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Converters\Object\ObjectConverterFactory.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.Generic;
 6using System.Diagnostics;
 7using System.Diagnostics.CodeAnalysis;
 8using System.Reflection;
 9using System.Text.Json.Reflection;
 10using System.Text.Json.Serialization.Metadata;
 11
 12namespace System.Text.Json.Serialization.Converters
 13{
 14    /// <summary>
 15    /// Converter factory for all object-based types (non-enumerable and non-primitive).
 16    /// </summary>
 17    [RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
 18    internal sealed class ObjectConverterFactory : JsonConverterFactory
 19    {
 20        // Need to toggle this behavior when generating converters for F# struct records.
 21        private readonly bool _useDefaultConstructorInUnannotatedStructs;
 22
 23        [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
 124        public ObjectConverterFactory(bool useDefaultConstructorInUnannotatedStructs = true)
 125        {
 126            _useDefaultConstructorInUnannotatedStructs = useDefaultConstructorInUnannotatedStructs;
 127        }
 28
 29        public override bool CanConvert(Type typeToConvert)
 83230        {
 31            // This is the last built-in factory converter, so if the IEnumerableConverterFactory doesn't
 32            // support it, then it is not IEnumerable.
 83233            Debug.Assert(!typeof(IEnumerable).IsAssignableFrom(typeToConvert));
 83234            return true;
 83235        }
 36
 37        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
 38            Justification = "The ctor is marked RequiresUnreferencedCode.")]
 39        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern",
 40            Justification = "The ctor is marked RequiresUnreferencedCode.")]
 41        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
 41642        {
 43            JsonConverter converter;
 44            Type converterType;
 45
 41646            bool useDefaultConstructorInUnannotatedStructs = _useDefaultConstructorInUnannotatedStructs && !typeToConver
 41647            if (!typeToConvert.TryGetDeserializationConstructor(useDefaultConstructorInUnannotatedStructs, out Construct
 048            {
 049                ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateTypeAttribute<JsonConstructorAttribute>
 50            }
 51
 41652            ParameterInfo[]? parameters = constructor?.GetParameters();
 53
 41654            if (constructor == null || typeToConvert.IsAbstract || parameters!.Length == 0)
 13055            {
 13056                converterType = typeof(ObjectDefaultConverter<>).MakeGenericType(typeToConvert);
 13057            }
 58            else
 28659            {
 28660                int parameterCount = parameters.Length;
 61
 429062                foreach (ParameterInfo parameter in parameters)
 171663                {
 64                    // Skip out parameters — they don't receive values from JSON
 65                    // and may reference unsupported types (e.g. Task).
 171666                    if (parameter.IsOut)
 067                    {
 068                        continue;
 69                    }
 70
 71                    // Every argument must be of supported type.
 72                    // For byref parameters (in/ref), validate the underlying element type.
 171673                    Type parameterType = parameter.ParameterType;
 171674                    if (parameterType.IsByRef)
 075                    {
 076                        parameterType = parameterType.GetElementType()!;
 077                    }
 78
 171679                    JsonTypeInfo.ValidateType(parameterType);
 171680                }
 81
 28682                if (parameterCount <= JsonConstants.UnboxedParameterCountThreshold)
 083                {
 084                    Type placeHolderType = typeof(object);
 085                    Type[] typeArguments = new Type[JsonConstants.UnboxedParameterCountThreshold + 1];
 86
 087                    typeArguments[0] = typeToConvert;
 088                    for (int i = 0; i < JsonConstants.UnboxedParameterCountThreshold; i++)
 089                    {
 090                        if (i < parameterCount)
 091                        {
 92                            // out parameters use placeholder type — they aren't deserialized
 93                            // and may reference types that can't be used as generic arguments.
 094                            if (parameters[i].IsOut)
 095                            {
 096                                typeArguments[i + 1] = placeHolderType;
 097                            }
 98                            else
 099                            {
 100                                // For byref parameters (in/ref), use the underlying element type
 101                                // since byref types cannot be used as generic type arguments.
 0102                                Type parameterType = parameters[i].ParameterType;
 0103                                if (parameterType.IsByRef)
 0104                                {
 0105                                    parameterType = parameterType.GetElementType()!;
 0106                                }
 107
 0108                                typeArguments[i + 1] = parameterType;
 0109                            }
 0110                        }
 111                        else
 0112                        {
 113                            // Use placeholder arguments if there are less args than the threshold.
 0114                            typeArguments[i + 1] = placeHolderType;
 0115                        }
 0116                    }
 117
 0118                    converterType = typeof(SmallObjectWithParameterizedConstructorConverter<,,,,>).MakeGenericType(typeA
 0119                }
 120                else
 286121                {
 286122                    converterType = typeof(LargeObjectWithParameterizedConstructorConverterWithReflection<>).MakeGeneric
 286123                }
 286124            }
 125
 416126            converter = (JsonConverter)Activator.CreateInstance(
 416127                    converterType,
 416128                    BindingFlags.Instance | BindingFlags.Public,
 416129                    binder: null,
 416130                    args: null,
 416131                    culture: null)!;
 132
 416133            converter.ConstructorInfo = constructor!;
 416134            return converter;
 416135        }
 136    }
 137}