Exemplo n.º 1
0
        // PRIVATE METHODS //////////////////////////////////////////////////
        #region Methods
        private static void AddOrUpdateApiTypeConfiguration <TConfiguration, TMutableFactory, TMutable>(IDictionary <Type, ApiTypeConfiguration> dictionary,
                                                                                                        ApiTypeConfiguration apiTypeConfiguration,
                                                                                                        Type apiTypeConfigurationOpenGenericType,
                                                                                                        ApiPrecedenceLevel apiPrecedenceLevel,
                                                                                                        ApiPrecedenceStack apiPrecedenceStack)
            where TConfiguration : ApiTypeConfiguration
            where TMutableFactory : ApiMutableFactory <ApiMutableSchema, TMutable>
        {
            Contract.Requires(dictionary != null);
            Contract.Requires(apiTypeConfiguration != null);
            Contract.Requires(apiTypeConfigurationOpenGenericType != null);
            Contract.Requires(apiPrecedenceStack != null);

            var apiConfigurationIncoming = (TConfiguration)apiTypeConfiguration;
            var apiObjectFactoryIncoming = (TMutableFactory)apiConfigurationIncoming.ApiMutableFactory;

            var clrType = apiTypeConfiguration.ClrType;

            if (dictionary.TryGetValue(clrType, out var apiConfiguration))
            {
                // Update the existing API configuration by merging the incoming derived API configuration.
                var apiConfigurationExisting = (TConfiguration)apiConfiguration;
                var apiObjectFactoryExisting = (TMutableFactory)apiConfigurationExisting.ApiMutableFactory;
                apiObjectFactoryExisting.Merge(apiObjectFactoryIncoming);
                return;
            }

            // Create a new API configuration from the incoming derived API configuration.
            var apiConfigurationNew = ApiTypeConfigurationFactory.CreateApiTypeConfiguration <TConfiguration, TMutableFactory, TMutable>(clrType, apiTypeConfigurationOpenGenericType, apiPrecedenceStack, apiObjectFactoryIncoming);

            dictionary.Add(clrType, apiConfigurationNew);

            ApiFrameworkLog.Trace($"Added {typeof(TConfiguration).Name} [ClrType={apiConfigurationNew.ClrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier));
        }
        private static ApiPropertyConfiguration GetOrAddApiPropertyConfiguration(ApiMutableObjectType apiMutableObjectType,
                                                                                 Type clrDeclaringType,
                                                                                 string clrPropertyName,
                                                                                 Type clrPropertyType,
                                                                                 ApiPrecedenceLevel apiPrecedenceLevel,
                                                                                 ApiPrecedenceStack apiPrecedenceStack)
        {
            Contract.Requires(apiMutableObjectType != null);
            Contract.Requires(clrDeclaringType != null);
            Contract.Requires(clrPropertyName.SafeHasContent());
            Contract.Requires(clrPropertyType != null);
            Contract.Requires(apiPrecedenceStack != null);

            if (apiMutableObjectType.ApiPropertyConfigurationsIndex.TryGetValue(clrPropertyName, out var apiPropertyConfigurationIndex))
            {
                var apiPropertyConfigurationExisting = apiMutableObjectType.ApiPropertyConfigurations[apiPropertyConfigurationIndex];
                return(apiPropertyConfigurationExisting);
            }

            var apiPropertyConfigurationNew      = new ApiPropertyConfiguration(clrDeclaringType, clrPropertyName, clrPropertyType, apiPrecedenceStack);
            var apiPropertyConfigurationIndexNew = apiMutableObjectType.ApiPropertyConfigurationsIndex.Count;

            apiMutableObjectType.ApiPropertyConfigurations.Add(apiPropertyConfigurationNew);
            apiMutableObjectType.ApiPropertyConfigurationsIndex.Add(clrPropertyName, apiPropertyConfigurationIndexNew);

            ApiFrameworkLog.Trace($"Added {nameof(ApiProperty)} [{nameof(ApiProperty.ClrName)}={clrPropertyName}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier));

            return(apiPropertyConfigurationNew);
        }
        private static IApiIdentity CreateApiIdentity(ApiMutableObjectType apiMutableObjectType, IEnumerable <IApiProperty> apiProperties)
        {
            Contract.Requires(apiMutableObjectType != null);
            Contract.Requires(apiProperties != null);

            var clrIdentityProperty = apiMutableObjectType.ClrIdentityProperty;

            if (clrIdentityProperty == null)
            {
                return(null);
            }

            var clrIdentityPropertyName = clrIdentityProperty.ClrPropertyName;

            if (String.IsNullOrWhiteSpace(clrIdentityPropertyName))
            {
                return(null);
            }

            var apiIdentityProperty = (ApiProperty)apiProperties.SingleOrDefault(x => x.ClrName == clrIdentityPropertyName);

            if (apiIdentityProperty == null)
            {
                var clrTypeName = apiMutableObjectType.ClrObjectType.Name;
                var message     = $"Unable to create API identity for an API object type [clrType={clrTypeName}] because the configured API identity property [clrName={clrIdentityPropertyName}] does not exist.";
                throw new ApiSchemaException(message);
            }

            var apiIdentity = ApiTypeFactory.CreateApiIdentity(apiIdentityProperty);

            ApiFrameworkLog.Debug($"Created {apiIdentity}".Indent(IndentConstants.ApiMutableObjectTypeIdentity));

            return(apiIdentity);
        }
        IApiObjectTypeBuilder IApiObjectTypeBuilder.ApiRelationship(string clrPropertyName, Type clrPropertyType)
        {
            Contract.Requires(clrPropertyName.SafeHasContent());
            Contract.Requires(clrPropertyType != null);

            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;

            this.ApiMutableObjectTypeFactory.AddModifier(apiConfigurationLevel,
                                                         x =>
            {
                // Preserve the order in which API relationships are added.
                if (x.ClrRelationshipPropertyIndexDictionary.TryGetValue(clrPropertyName, out var clrRelationshipPropertyIndex))
                {
                    return;
                }

                var clrRelationshipProperty  = new ClrRelationshipProperty(clrPropertyName, clrPropertyType);
                clrRelationshipPropertyIndex = x.ClrRelationshipPropertyIndexDictionary.Count;

                ApiFrameworkLog.Trace($"Added {clrRelationshipProperty} at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier));

                x.ClrRelationshipPropertyCollection.Add(clrRelationshipProperty);
                x.ClrRelationshipPropertyIndexDictionary.Add(clrPropertyName, clrRelationshipPropertyIndex);
            },
                                                         CallerTypeName);
            return(this);
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiSchemaBuilder Implementation
        public IApiSchemaBuilder Exclude(Type clrType)
        {
            Contract.Requires(clrType != null);

            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;
            var apiTypeKind           = clrType.GetApiTypeKind();

            switch (apiTypeKind)
            {
            case ApiTypeKind.Object:
            {
                this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel,
                                                         x =>
                    {
                        ApiFrameworkLog.Trace(
                            $"Excluded {nameof(Schema.Internal.ApiObjectType)} [{nameof(Schema.Internal.ApiObjectType.ClrType)}={clrType.Name}] at {apiConfigurationLevel} Level".Indent(
                                IndentConstants.ApiMutableSchemaModifier));
                        x.AddClrExcludedObjectType(clrType);
                    },
                                                         CallerTypeName);
                break;
            }

            case ApiTypeKind.Scalar:
            {
                this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel,
                                                         x =>
                    {
                        ApiFrameworkLog.Trace(
                            $"Excluded {nameof(Schema.Internal.ApiScalarType)} [{nameof(Schema.Internal.ApiScalarType.ClrType)}={clrType.Name}] at {apiConfigurationLevel} Level".Indent(
                                IndentConstants.ApiMutableSchemaModifier));
                        x.AddClrExcludedScalarType(clrType);
                    },
                                                         CallerTypeName);
                break;
            }

            case ApiTypeKind.Enumeration:
            {
                this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel,
                                                         x =>
                    {
                        ApiFrameworkLog.Trace(
                            $"Excluded {nameof(Schema.Internal.ApiEnumerationType)} [{nameof(Schema.Internal.ApiEnumerationType.ClrType)}={clrType.Name}] at {apiConfigurationLevel} Level".Indent(
                                IndentConstants.ApiMutableSchemaModifier));
                        x.AddClrExcludedEnumerationType(clrType);
                    },
                                                         CallerTypeName);
                break;
            }
            }

            return(this);
        }
        public IApiEnumerationValue Create(ApiMutableSchema apiMutableSchema)
        {
            Contract.Requires(apiMutableSchema != null);

            var apiMutableEnumerationValue = this.ApiMutableEnumerationValueFactory.Create(apiMutableSchema);

            var apiEnumerationValue = CreateApiEnumerationValue(apiMutableEnumerationValue);

            ApiFrameworkLog.Debug($"Created {apiEnumerationValue}".Indent(IndentConstants.ApiEnumerationValue));

            return(apiEnumerationValue);
        }
Exemplo n.º 7
0
        internal override IApiType CreateApiType(ApiMutableType apiMutableType, ApiSchemaProxy apiSchemaProxy)
        {
            Contract.Requires(apiMutableType != null);
            Contract.Requires(apiSchemaProxy != null);

            var apiMutableScalarType = (ApiMutableScalarType)apiMutableType;

            var apiScalarType = CreateApiScalarType(apiMutableScalarType);

            ApiFrameworkLog.Debug($"Created {apiScalarType}".Indent(IndentConstants.ApiScalarType));

            return(apiScalarType);
        }
Exemplo n.º 8
0
        public IApiCollectionType Create(ApiMutableSchema apiMutableSchema, ApiSchemaProxy apiSchemaProxy)
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiSchemaProxy != null);

            var apiMutableCollectionType = this.CreateApiMutableType(apiMutableSchema);

            var apiCollectionType = (IApiCollectionType)this.CreateApiType(apiMutableCollectionType, apiSchemaProxy);

            ApiFrameworkLog.Debug($"Created {apiCollectionType}".Indent(IndentConstants.ApiCollectionType));

            return(apiCollectionType);
        }
Exemplo n.º 9
0
        public IApiProperty CreateApiProperty(ApiMutableSchema apiMutableSchema, ApiMutableObjectType apiMutableObjectType, ApiSchemaProxy apiSchemaProxy)
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiMutableObjectType != null);
            Contract.Requires(apiSchemaProxy != null);

            var apiMutableProperty = this.ApiMutablePropertyFactory.Create(apiMutableSchema);

            var apiProperty = CreateApiProperty(apiMutableObjectType, apiMutableProperty, apiSchemaProxy);

            ApiFrameworkLog.Debug($"Created {apiProperty}".Indent(IndentConstants.ApiProperty));

            return(apiProperty);
        }
Exemplo n.º 10
0
        private static TApiConfiguration GetOrAddApiConfiguration <TApiConfiguration>(IDictionary <Type, ApiTypeConfiguration> dictionary,
                                                                                      Type clrType,
                                                                                      Type apiConfigurationOpenGenericType,
                                                                                      ApiPrecedenceLevel apiPrecedenceLevel,
                                                                                      ApiPrecedenceStack apiPrecedenceStack)
            where TApiConfiguration : ApiTypeConfiguration
        {
            Contract.Requires(dictionary != null);
            Contract.Requires(clrType != null);
            Contract.Requires(apiConfigurationOpenGenericType != null);
            Contract.Requires(apiPrecedenceStack != null);

            if (dictionary.TryGetValue(clrType, out var apiConfiguration))
            {
                var apiConfigurationExisting = (TApiConfiguration)apiConfiguration;
                return(apiConfigurationExisting);
            }

            var apiConfigurationNew = ApiTypeConfigurationFactory.CreateApiTypeConfiguration <TApiConfiguration>(clrType, apiConfigurationOpenGenericType, apiPrecedenceStack);

            dictionary.Add(clrType, apiConfigurationNew);

            var apiTypeKind = apiConfigurationNew.ApiTypeKind;

            switch (apiTypeKind)
            {
            case ApiTypeKind.Enumeration:
            {
                ApiFrameworkLog.Trace($"Added {nameof(ApiEnumerationType)} [{nameof(ApiEnumerationType.ClrType)}={clrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier));
                break;
            }

            case ApiTypeKind.Object:
            {
                ApiFrameworkLog.Trace($"Added {nameof(ApiObjectType)} [{nameof(ApiObjectType.ClrType)}={clrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier));
                break;
            }

            case ApiTypeKind.Scalar:
            {
                ApiFrameworkLog.Trace($"Added {nameof(ApiScalarType)} [{nameof(ApiScalarType.ClrType)}={clrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier));
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(apiConfigurationNew);
        }
        public IApiSchema Create(ApiSchemaFactorySettings apiSchemaFactorySettings)
        {
            ApiFrameworkLog.Debug($"Creating {nameof(ApiSchema)}".Indent(IndentConstants.ApiSchema));

            var apiMutableSchema = this.ApiMutableSchemaFactory.Create(apiSchemaFactorySettings);

            var apiSchema = CreateApiSchema(apiMutableSchema, this.ApiPrecedenceStack);

            var createdApiSchema = apiSchema.ToTreeString();

            ApiFrameworkLog.Information($"Created {nameof(ApiSchema)}" + "\n" + "{CreatedApiSchema}".Indent(IndentConstants.ApiSchema), createdApiSchema);

            return(apiSchema);
        }
        public IApiSchemaBuilder HasName(string apiName)
        {
            Contract.Requires(apiName.SafeHasContent());

            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;

            this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel,
                                                     x =>
            {
                ApiFrameworkLog.Trace($"Modified {nameof(x.ApiName)} '{x.ApiName}' => '{apiName}' at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier));
                x.ApiName = apiName;
            },
                                                     CallerTypeName);
            return(this);
        }
Exemplo n.º 13
0
        public IApiPropertyBuilder IsRequired()
        {
            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;

            this.ApiMutablePropertyFactory.AddModifier(apiConfigurationLevel,
                                                       x =>
            {
                var apiTypeModifiers = x.ApiTypeModifiers;
                x.ApiTypeModifiers  |= ApiTypeModifiers.Required;
                ApiFrameworkLog.Trace($"Modified {nameof(x.ApiTypeModifiers)} '{apiTypeModifiers}' => '{x.ApiTypeModifiers}' at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutablePropertyModifier));
            },
                                                       CallerTypeName);

            return(this);
        }
Exemplo n.º 14
0
        public IApiPropertyBuilder HasDescription(string apiDescription)
        {
            Contract.Requires(apiDescription.SafeHasContent());

            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;

            this.ApiMutablePropertyFactory.AddModifier(apiConfigurationLevel,
                                                       x =>
            {
                ApiFrameworkLog.Trace($"Modified {nameof(x.ApiDescription)} '{x.ApiDescription}' => '{apiDescription}' at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutablePropertyModifier));
                x.ApiDescription = apiDescription;
            },
                                                       CallerTypeName);
            return(this);
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeBuilder Implementation
        IApiObjectTypeBuilder IApiObjectTypeBuilder.Exclude(string clrPropertyName)
        {
            Contract.Requires(clrPropertyName.SafeHasContent());

            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;

            this.ApiMutableObjectTypeFactory.AddModifier(apiConfigurationLevel,
                                                         x =>
            {
                ApiFrameworkLog.Trace($"Excluded {nameof(ApiProperty)} [{nameof(ApiProperty.ClrName)}={clrPropertyName}] at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier));
                x.ClrExcludedPropertyNames.Add(clrPropertyName);
            },
                                                         CallerTypeName);
            return(this);
        }
        private static IEnumerable <IApiObjectType> CreateApiObjectTypes(ApiMutableSchema apiMutableSchema,
                                                                         ApiSchemaProxy apiSchemaProxy)
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiSchemaProxy != null);

            ApiFrameworkLog.Debug($"Creating {nameof(ApiObjectType)}s".Indent(IndentConstants.ApiObjectTypes));

            var apiObjectTypeConfigurations = apiMutableSchema.ApiObjectTypeConfigurationDictionary
                                              .Values
                                              .ToList();
            var clrExcludedObjectTypes = apiMutableSchema.ClrExcludedObjectTypes;
            var apiObjectTypes         = CreateApiTypes <IApiObjectType>(apiMutableSchema, apiSchemaProxy, apiObjectTypeConfigurations, clrExcludedObjectTypes);

            ApiFrameworkLog.Debug($"Created {nameof(ApiObjectType)}s".Indent(IndentConstants.ApiObjectTypes));

            return(apiObjectTypes);
        }
        private static IEnumerable <IApiEnumerationType> CreateApiEnumerationTypes(ApiMutableSchema apiMutableSchema,
                                                                                   ApiPrecedenceStack apiPrecedenceStack,
                                                                                   ApiSchemaProxy apiSchemaProxy)
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiPrecedenceStack != null);

            ApiFrameworkLog.Debug($"Creating {nameof(ApiEnumerationType)}s".Indent(IndentConstants.ApiEnumerationTypes));

            RemoveUnusedApiEnumerationTypes(apiMutableSchema);
            AddMissingApiEnumerationTypes(apiMutableSchema, apiPrecedenceStack);

            var apiEnumerationTypeConfigurations = apiMutableSchema.ApiEnumerationTypeConfigurationDictionary
                                                   .Values
                                                   .ToList();
            var clrExcludedEnumerationTypes = apiMutableSchema.ClrExcludedEnumerationTypes;
            var apiEnumerationTypes         = CreateApiTypes <IApiEnumerationType>(apiMutableSchema, apiSchemaProxy, apiEnumerationTypeConfigurations, clrExcludedEnumerationTypes);

            ApiFrameworkLog.Debug($"Created {nameof(ApiEnumerationType)}s".Indent(IndentConstants.ApiEnumerationTypes));

            return(apiEnumerationTypes);
        }
        IApiObjectTypeBuilder IApiObjectTypeBuilder.ApiIdentity(string clrPropertyName, Type clrPropertyType)
        {
            Contract.Requires(clrPropertyName.SafeHasContent());
            Contract.Requires(clrPropertyType != null);

            var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel;

            this.ApiMutableObjectTypeFactory.AddModifier(apiConfigurationLevel,
                                                         x =>
            {
                // This API object type is an API resource type because it has identity, register with the mutable API schema object.
                var clrObjectType    = x.ClrObjectType;
                var apiMutableSchema = x.ApiMutableSchema;
                apiMutableSchema.AddClrResourceType(clrObjectType);

                var clrIdentityProperty = new ClrIdentityProperty(clrPropertyName, clrPropertyType);
                ApiFrameworkLog.Trace($"Set {clrIdentityProperty} at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier));

                x.ClrIdentityProperty = clrIdentityProperty;
            },
                                                         CallerTypeName);
            return(this);
        }
        private static ApiEnumerationValueConfiguration GetOrAddApiEnumerationValueConfiguration(ApiMutableEnumerationType apiMutableEnumerationType,
                                                                                                 string clrName,
                                                                                                 int clrOrdinal,
                                                                                                 ApiPrecedenceLevel apiPrecedenceLevel,
                                                                                                 ApiPrecedenceStack apiPrecedenceStack)
        {
            Contract.Requires(apiMutableEnumerationType != null);
            Contract.Requires(clrName.SafeHasContent());
            Contract.Requires(apiPrecedenceStack != null);

            if (apiMutableEnumerationType.ApiEnumerationValueConfigurations.TryGetValue(clrOrdinal, out var apiEnumerationValueConfigurationExisting))
            {
                return(apiEnumerationValueConfigurationExisting);
            }

            var apiEnumerationValueConfigurationNew = new ApiEnumerationValueConfiguration(clrName, clrOrdinal, apiPrecedenceStack);

            apiMutableEnumerationType.ApiEnumerationValueConfigurations.Add(clrOrdinal, apiEnumerationValueConfigurationNew);

            ApiFrameworkLog.Trace($"Added {nameof(ApiEnumerationValue)} [{nameof(ApiEnumerationValue.ClrName)}={clrName}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableEnumerationTypeModifier));

            return(apiEnumerationValueConfigurationNew);
        }
        // ReSharper disable once ReturnTypeCanBeEnumerable.Local
        private static IReadOnlyCollection <IApiRelationship> CreateApiRelationships(ApiMutableObjectType apiMutableObjectType,
                                                                                     ApiSchemaProxy apiSchemaProxy,
                                                                                     IEnumerable <IApiProperty> apiProperties,
                                                                                     IApiIdentity apiIdentity)
        {
            Contract.Requires(apiMutableObjectType != null);
            Contract.Requires(apiSchemaProxy != null);
            Contract.Requires(apiProperties != null);

            // If this API object type has no identity, it may not contain any relationships.
            if (apiIdentity == null)
            {
                return(null);
            }

            var apiMutableSchema = apiMutableObjectType.ApiMutableSchema;
            var clrRelationshipPropertyCollection = apiMutableObjectType.ClrRelationshipPropertyCollection;
            var apiRelationships = clrRelationshipPropertyCollection
                                   .Where(x =>
            {
                // Can not create an API relationship if the related API object type does not have identity (must be an API resource type).
                var clrPropertyType     = x.ClrPropertyType;
                var apiPropertyTypeKind = clrPropertyType.GetApiTypeKind(out var clrPropertyItemType);
                switch (apiPropertyTypeKind)
                {
                case ApiTypeKind.Object:
                    {
                        var isApiResourceType = apiMutableSchema.ClrResourceTypes.Contains(clrPropertyType);
                        if (!isApiResourceType)
                        {
                            return(false);
                        }

                        break;
                    }

                case ApiTypeKind.Collection:
                    {
                        var apiItemTypeKind = clrPropertyItemType.GetApiTypeKind();
                        switch (apiItemTypeKind)
                        {
                        case ApiTypeKind.Collection:
                            {
                                // Unable to handle collections within collections.
                                var message = $"Unable to create API relationship for an API property [{nameof(x.ClrPropertyName)}={x.ClrPropertyName}] that contains collections within collections";
                                throw new ApiSchemaException(message);
                            }
                        }

                        var isApiResourceType = apiMutableSchema.ClrResourceTypes.Contains(clrPropertyItemType);
                        if (!isApiResourceType)
                        {
                            return(false);
                        }

                        break;
                    }

                default:
                    {
                        return(false);
                    }
                }

                return(true);
            })
                                   .Select(x =>
            {
                var clrPropertyName     = x.ClrPropertyName;
                var clrPropertyType     = x.ClrPropertyType;
                var apiProperty         = apiProperties.Single(y => y.ClrName == clrPropertyName);
                var apiPropertyTypeKind = clrPropertyType.GetApiTypeKind(out var clrPropertyItemType);

                ApiRelationshipCardinality apiCardinality;
                Type clrType;
                switch (apiPropertyTypeKind)
                {
                case ApiTypeKind.Object:
                    {
                        apiCardinality = ApiRelationshipCardinality.ToOne;
                        clrType        = clrPropertyType;
                        break;
                    }

                case ApiTypeKind.Collection:
                    {
                        apiCardinality = ApiRelationshipCardinality.ToMany;
                        clrType        = clrPropertyItemType;
                        break;
                    }

                default:
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                }

                var apiRelatedTypeResolver = new ApiSchemaProxyTypeResolver(apiSchemaProxy, ApiTypeKind.Object, clrType);
                var apiRelationship        = ApiTypeFactory.CreateApiRelationship(apiProperty, apiCardinality, apiRelatedTypeResolver);

                return(apiRelationship);
            })
                                   .ToList();

            foreach (var apiRelationship in apiRelationships)
            {
                ApiFrameworkLog.Debug($"Created {apiRelationship}".Indent(IndentConstants.ApiMutableObjectTypeRelationship));
            }

            return(apiRelationships);
        }