예제 #1
0
        internal JsonClassInfo(Type type, JsonSerializerOptions options)
        {
            Type      = type;
            ClassType = GetClassType(type);

            CreateObject = options.ClassMaterializerStrategy.CreateConstructor(type);

            // Ignore properties on enumerable.
            switch (ClassType)
            {
            case ClassType.Object:
                var propertyNames = new HashSet <string>(StringComparer.Ordinal);

                foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    // For now we only support public getters\setters
                    if (propertyInfo.GetMethod?.IsPublic == true ||
                        propertyInfo.SetMethod?.IsPublic == true)
                    {
                        JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options);

                        Debug.Assert(jsonPropertyInfo.NameUsedToCompareAsString != null);

                        // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception.
                        if (!propertyNames.Add(jsonPropertyInfo.NameUsedToCompareAsString))
                        {
                            ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(this, jsonPropertyInfo);
                        }

                        jsonPropertyInfo.ClearUnusedValuesAfterAdd();
                    }
                }

                DetermineExtensionDataProperty();
                break;

            case ClassType.Enumerable:
            case ClassType.Dictionary:
                // Add a single property that maps to the class type so we can have policies applied.
                JsonPropertyInfo policyProperty = AddPolicyProperty(type, options);

                // Use the type from the property policy to get any late-bound concrete types (from an interface like IDictionary).
                CreateObject = options.ClassMaterializerStrategy.CreateConstructor(policyProperty.RuntimePropertyType);

                // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies.
                Type elementType = GetElementType(type, parentType: null, memberInfo: null);
                ElementClassInfo = options.GetOrAddClass(elementType);
                break;

            case ClassType.Value:
            case ClassType.Unknown:
                // Add a single property that maps to the class type so we can have policies applied.
                AddPolicyProperty(type, options);
                break;

            default:
                Debug.Fail($"Unexpected class type: {ClassType}");
                break;
            }
        }
예제 #2
0
        internal JsonClassInfo(Type type, JsonSerializerOptions options)
        {
            Type      = type;
            ClassType = GetClassType(type);

            CreateObject = options.ClassMaterializerStrategy.CreateConstructor(type);

            // Ignore properties on enumerable.
            if (ClassType == ClassType.Object)
            {
                var propertyNames = new HashSet <string>(StringComparer.Ordinal);

                foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    // For now we only support public getters\setters
                    if (propertyInfo.GetMethod?.IsPublic == true ||
                        propertyInfo.SetMethod?.IsPublic == true)
                    {
                        JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options);

                        if (jsonPropertyInfo.NameAsString == null)
                        {
                            ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(this, jsonPropertyInfo);
                        }

                        // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception.
                        if (!propertyNames.Add(jsonPropertyInfo.CompareNameAsString))
                        {
                            ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(this, jsonPropertyInfo);
                        }

                        jsonPropertyInfo.ClearUnusedValuesAfterAdd();
                    }
                }
            }
            else if (ClassType == ClassType.Enumerable || ClassType == ClassType.Dictionary)
            {
                // Add a single property that maps to the class type so we can have policies applied.
                JsonPropertyInfo jsonPropertyInfo = AddProperty(type, propertyInfo: null, type, options);

                // Use the type from the property policy to get any late-bound concrete types (from an interface like IDictionary).
                CreateObject = options.ClassMaterializerStrategy.CreateConstructor(jsonPropertyInfo.RuntimePropertyType);

                // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies.
                Type elementType = GetElementType(type);

                ElementClassInfo = options.GetOrAddClass(elementType);
            }
            else if (ClassType == ClassType.Value)
            {
                // Add a single property that maps to the class type so we can have policies applied.
                AddProperty(type, propertyInfo: null, type, options);
            }
            else
            {
                Debug.Assert(ClassType == ClassType.Unknown);
                // Do nothing. The type is typeof(object).
            }
        }