public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var valueOfProperty        = new Dictionary <PropertyInfo, object>();
            var namedPropertiesMapping = GetNamedProperties(options, GetProperties(typeToConvert));

            reader.Read();
            while (true)
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    break;
                }

                if (reader.TokenType != JsonTokenType.PropertyName)
                {
                    reader.Read();
                }
                else
                {
                    var jsonPropName = reader.GetString();
                    if (!string.IsNullOrEmpty(jsonPropName))
                    {
                        var normalizedPropName = ConvertAndNormalizeName(jsonPropName, options);
                        if (!namedPropertiesMapping.TryGetValue(normalizedPropName, out var obProp))
                        {
                            reader.Read();
                        }
                        else
                        {
                            var value = JsonSerializer.Deserialize(ref reader, obProp.PropertyType, options);
                            reader.Read();
                            valueOfProperty[obProp] = value;
                        }
                    }
                }
            }

            var ctor            = typeToConvert.GetConstructors(BindingFlags.Public | BindingFlags.Instance).First();
            var parameters      = ctor.GetParameters();
            var parameterValues = new object[parameters.Length];

            for (var index = 0; index < parameters.Length; index++)
            {
                var parameterInfo = parameters[index];
                var value         = valueOfProperty.FirstOrDefault(prop =>
                                                                   NameOfPropertyAndParameter.Matches(prop.Key.Name, parameterInfo.Name, typeToConvert.IsAnonymous())).Value;

                parameterValues[index] = value;
            }

            var instance = ctor.Invoke(parameterValues);

            return(instance);
        }
        public override bool CanConvert(Type typeToConvert)
        {
            if (typeToConvert.IsPrimitive)
            {
                return(false);
            }

            var nullableUnderlyingType = Nullable.GetUnderlyingType(typeToConvert);

            if (nullableUnderlyingType != null && nullableUnderlyingType.IsValueType)
            {
                return(false);
            }

            bool result;
            var  constructors = typeToConvert.GetConstructors(BindingFlags.Public | BindingFlags.Instance);

            if (constructors.Length != 1)
            {
                result = false;
            }
            else
            {
                var constructor   = constructors[0];
                var parameters    = constructor.GetParameters();
                var hasParameters = parameters.Length > 0;
                if (hasParameters)
                {
                    var properties = typeToConvert.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                    result = true;
                    foreach (var parameter in parameters)
                    {
                        var hasMatchingProperty = properties.Any(p =>
                                                                 NameOfPropertyAndParameter.Matches(p.Name, parameter.Name, typeToConvert.IsAnonymous()));
                        if (!hasMatchingProperty)
                        {
                            result = false;
                            break;
                        }
                    }
                }
                else
                {
                    result = false;
                }
            }

            return(result);
        }