private void AddPropertyInfoFromPropertySchema(
            IList <KeyValuePair <string, PropertyInfo> > entries,
            string schemaPropertyName,
            JsonSchema propertySchema,
            bool isRequired)
        {
            ComparisonKind     comparisonKind;
            HashKind           hashKind;
            InitializationKind initializationKind;
            TypeSyntax         type;
            string             namespaceName = null;
            string             referencedEnumTypeName;
            bool isOfSchemaDefinedType = false;
            int  arrayRank             = 0;

            if (propertySchema.IsDateTime())
            {
                comparisonKind     = ComparisonKind.OperatorEquals;
                hashKind           = HashKind.ScalarValueType;
                initializationKind = InitializationKind.SimpleAssign;
                type = MakeNamedType("System.DateTime", out namespaceName);
            }
            else if (propertySchema.IsUri())
            {
                comparisonKind     = ComparisonKind.OperatorEquals;
                hashKind           = HashKind.ScalarReferenceType;
                initializationKind = InitializationKind.Uri;
                type = MakeNamedType("System.Uri", out namespaceName);
            }
            else if (propertySchema.ShouldBeDictionary(_typeName, schemaPropertyName, _hintDictionary, out DictionaryHint dictionaryHint))
            {
                comparisonKind     = ComparisonKind.Dictionary;
                hashKind           = HashKind.Dictionary;
                initializationKind = InitializationKind.Dictionary;

                // If the schema for this property specifies additionalProperties, and if
                // the value of additionalProperties is a schema as opposed to a Boolean,
                // then we will represent this property as a dictionary from string to
                // whatever kind of object the schema represents. Otherwise, treat it as
                // a dictionary from string to string.
                JsonSchema dictionaryElementSchema = propertySchema.AdditionalProperties?.Schema != null
                    ? propertySchema.AdditionalProperties.Schema
                    : new JsonSchema {
                    Type = new SchemaType[] { SchemaType.String }
                };

                type          = MakeDictionaryType(entries, schemaPropertyName, dictionaryHint, dictionaryElementSchema);
                namespaceName = "System.Collections.Generic";   // For IDictionary.
            }
            else if ((referencedEnumTypeName = GetReferencedEnumTypeName(propertySchema)) != null)
            {
                comparisonKind     = ComparisonKind.OperatorEquals;
                hashKind           = HashKind.ScalarValueType;
                initializationKind = InitializationKind.SimpleAssign;
                type = MakeNamedType(referencedEnumTypeName, out namespaceName);
            }
            else if (propertySchema.ShouldBeEnum(_typeName, schemaPropertyName, _hintDictionary, out EnumHint enumHint))
            {
                comparisonKind     = ComparisonKind.OperatorEquals;
                hashKind           = HashKind.ScalarValueType;
                initializationKind = InitializationKind.SimpleAssign;
                type = MakeNamedType(enumHint.TypeName, out namespaceName);

                // The class whose property info we are generating contains a property
                // of an enumerated type. Notify the code generator that it must generate
                // the enumerated type in addition to the current type.
                OnAdditionalTypeRequired(enumHint, propertySchema);
            }
            else
            {
                SchemaType propertyType = propertySchema.SafeGetType();

                switch (propertyType)
                {
                case SchemaType.Boolean:
                case SchemaType.Integer:
                case SchemaType.Number:
                    comparisonKind     = ComparisonKind.OperatorEquals;
                    hashKind           = HashKind.ScalarValueType;
                    initializationKind = InitializationKind.SimpleAssign;
                    type = MakePrimitiveType(propertyType);
                    break;

                case SchemaType.String:
                    comparisonKind     = ComparisonKind.OperatorEquals;
                    hashKind           = HashKind.ScalarReferenceType;
                    initializationKind = InitializationKind.SimpleAssign;
                    type = MakePrimitiveType(propertyType);
                    break;

                case SchemaType.Object:
                    // If the schema for this property references a named type,
                    // the generated Init method will initialize it by cloning an object
                    // of that type. Otherwise, we treat this property as a System.Object
                    // and just initialize it by assignment.
                    if (propertySchema.Reference != null)
                    {
                        comparisonKind        = ComparisonKind.EqualityComparerEquals;
                        initializationKind    = InitializationKind.Clone;
                        hashKind              = HashKind.ObjectModelType;
                        isOfSchemaDefinedType = true;
                    }
                    else
                    {
                        comparisonKind     = ComparisonKind.ObjectEquals;
                        initializationKind = InitializationKind.SimpleAssign;
                        hashKind           = HashKind.ScalarReferenceType;
                    }

                    type = MakeObjectType(propertySchema, out namespaceName);
                    break;

                case SchemaType.Array:
                    comparisonKind     = ComparisonKind.Collection;
                    hashKind           = HashKind.Collection;
                    initializationKind = InitializationKind.Collection;
                    namespaceName      = "System.Collections.Generic";  // For IList.
                    type = MakeArrayType(entries, schemaPropertyName, propertySchema);
                    break;

                case SchemaType.None:
                    SchemaType inferredType = InferSchemaTypeFromEnumValues(propertySchema.Enum);
                    if (inferredType == SchemaType.None)
                    {
                        comparisonKind     = ComparisonKind.ObjectEquals;
                        hashKind           = HashKind.ScalarReferenceType;
                        initializationKind = InitializationKind.None;
                        type = MakePrimitiveType(SchemaType.Object);
                        break;
                    }
                    else if (inferredType == SchemaType.String)
                    {
                        comparisonKind     = ComparisonKind.OperatorEquals;
                        hashKind           = HashKind.ScalarReferenceType;
                        initializationKind = InitializationKind.SimpleAssign;
                        type = MakePrimitiveType(SchemaType.String);
                        break;
                    }
                    else
                    {
                        comparisonKind     = ComparisonKind.OperatorEquals;
                        hashKind           = HashKind.ScalarValueType;
                        initializationKind = InitializationKind.SimpleAssign;
                        type = MakePrimitiveType(inferredType);
                        break;
                    }

                default:
                    throw new ArgumentOutOfRangeException(nameof(propertySchema.Type));
                }
            }

            var    propertyNameHint   = _hintDictionary?.GetHint <PropertyNameHint>(_typeName + "." + schemaPropertyName);
            string dotNetPropertyName = propertyNameHint != null
                ? propertyNameHint.DotNetPropertyName
                : schemaPropertyName.ToPascalCase();

            entries.Add(new KeyValuePair <string, PropertyInfo>(
                            dotNetPropertyName,
                            new PropertyInfo(
                                propertySchema.Description,
                                schemaPropertyName,
                                comparisonKind,
                                hashKind,
                                initializationKind,
                                type,
                                namespaceName,
                                isRequired,
                                propertySchema.Default,
                                isOfSchemaDefinedType,
                                arrayRank,
                                entries.Count)));
        }