예제 #1
0
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiSchemaConvention Implementation
        public void Apply(IApiSchemaBuilder apiSchemaBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiSchemaBuilder != null);

            apiConventionSettings = apiConventionSettings ?? ApiConventionSettings.Empty;
            var apiDiscoverySettings = apiConventionSettings.ApiDiscoverySettings;
            var assemblies           = apiDiscoverySettings.Assemblies;
            var clrTypes             = assemblies.SelectMany(x => x.GetExportedTypes())
                                       .ToList();

            foreach (var clrType in clrTypes)
            {
                var apiTypeKind = clrType.GetApiTypeKind();
                switch (apiTypeKind)
                {
                case ApiTypeKind.Object:
                {
                    if (ClrTypeDiscoveryRules.CanAddApiObjectType(clrType) == false)
                    {
                        continue;
                    }

                    var apiTypeDiscoveryPredicateResult = apiDiscoverySettings.ApiTypeDiscoveryPredicate?.Invoke(clrType) ?? true;
                    if (apiTypeDiscoveryPredicateResult == false)
                    {
                        continue;
                    }

                    apiSchemaBuilder.ApiObjectType(clrType);
                    break;
                }
                }
            }
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeConvention Implementation
        public void Apply(IApiObjectTypeBuilder apiObjectTypeBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiObjectTypeBuilder != null);

            // Try and discover the identity CLR property of the CLR object type:
            var clrObjectType = apiObjectTypeBuilder.ClrType;
            var clrProperties = ClrPropertyDiscoveryRules.GetClrProperties(clrObjectType);

            // 1. By convention, any CLR property named "Id" is the identity CLR property for this CLR object type.
            var clrIdProperty = ClrPropertyDiscoveryRules.GetClrPropertyByName(clrProperties, "Id");

            if (clrIdProperty != null)
            {
                // Call ApiIdentity method on the discovered CLR property.
                var clrIdPropertyName = clrIdProperty.Name;
                var clrIdPropertyType = clrIdProperty.PropertyType;
                apiObjectTypeBuilder.ApiIdentity(clrIdPropertyName, clrIdPropertyType);
                return;
            }

            // 2. By convention, any CLR property named "XXXId" where XXX is the CLR class name is the identity CLR property for this CLR object type.
            var clrClassName              = clrObjectType.Name;
            var clrClassNameAndId         = $"{clrClassName}Id";
            var clrClassNameAndIdProperty = ClrPropertyDiscoveryRules.GetClrPropertyByName(clrProperties, clrClassNameAndId);

            // ReSharper disable once InvertIf
            if (clrClassNameAndIdProperty != null)
            {
                // Call ApiIdentity method on the discovered CLR property.
                var clrClassNameAndIdPropertyName = clrClassNameAndIdProperty.Name;
                var clrClassNameAndIdPropertyType = clrClassNameAndIdProperty.PropertyType;
                apiObjectTypeBuilder.ApiIdentity(clrClassNameAndIdPropertyName, clrClassNameAndIdPropertyType);
            }
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiSchemaConvention Implementation
        public void Apply(IApiSchemaBuilder apiSchemaBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiSchemaBuilder != null);

            apiConventionSettings = apiConventionSettings ?? ApiConventionSettings.Empty;
            var apiDiscoverySettings = apiConventionSettings.ApiDiscoverySettings;
            var assemblies           = apiDiscoverySettings.Assemblies;
            var clrTypes             = assemblies.SelectMany(x => x.GetExportedTypes())
                                       .ToList();

            foreach (var clrType in clrTypes)
            {
                if (ClrTypeDiscoveryRules.CanAddApiTypeConfiguration(clrType) == false)
                {
                    continue;
                }

                var apiConfigurationDiscoveryPredicateResult = apiDiscoverySettings.ApiConfigurationDiscoveryPredicate?.Invoke(clrType) ?? true;
                if (apiConfigurationDiscoveryPredicateResult == false)
                {
                    continue;
                }

                var apiTypeConfigurationNewExpression = ExpressionBuilder.New <ApiTypeConfiguration>(clrType);
                var apiTypeConfigurationNewLambda     = apiTypeConfigurationNewExpression.Compile();
                var apiTypeConfiguration = apiTypeConfigurationNewLambda();

                apiSchemaBuilder.HasConfiguration(apiTypeConfiguration);
            }
        }
예제 #4
0
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiSchemaConvention Implementation
        public void Apply(IApiSchemaBuilder apiSchemaBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiSchemaBuilder != null);

            apiConventionSettings = apiConventionSettings ?? ApiConventionSettings.Empty;
            var apiDiscoverySettings = apiConventionSettings.ApiDiscoverySettings;
            var assemblies           = apiDiscoverySettings.Assemblies;
            var clrTypes             = assemblies.SelectMany(x => x.GetExportedTypes())
                                       .ToList();

            var apiSchemaConfiguration = (ApiSchemaConfiguration)apiSchemaBuilder;
            var apiPrecedenceStack     = apiSchemaConfiguration.ApiPrecedenceStack;

            foreach (var clrType in clrTypes)
            {
                var apiTypeKind = clrType.GetApiTypeKind();
                switch (apiTypeKind)
                {
                case ApiTypeKind.Enumeration:
                {
                    this.HandleApiEnumerationTypeAttribute(apiSchemaConfiguration, apiConventionSettings, apiPrecedenceStack, clrType);
                    break;
                }

                case ApiTypeKind.Object:
                {
                    this.HandleApiObjectTypeAttribute(apiSchemaConfiguration, apiConventionSettings, apiPrecedenceStack, clrType);
                    break;
                }
                }
            }
        }
예제 #5
0
        private void HandleApiObjectTypeAttribute(IApiSchemaBuilder apiSchemaBuilder,
                                                  ApiConventionSettings apiConventionSettings,
                                                  ApiPrecedenceStack apiPrecedenceStack,
                                                  Type clrType)
        {
            Contract.Requires(apiSchemaBuilder != null);
            Contract.Requires(apiConventionSettings != null);
            Contract.Requires(clrType != null);

            var apiObjectTypeAttribute = (ApiObjectTypeAttribute)Attribute.GetCustomAttribute(clrType, typeof(ApiObjectTypeAttribute));

            if (apiObjectTypeAttribute == null)
            {
                return;
            }

            if (ClrTypeDiscoveryRules.CanAddApiObjectType(clrType) == false)
            {
                return;
            }

            var apiDiscoverySettings = apiConventionSettings.ApiDiscoverySettings;
            var apiAnnotationDiscoveryPredicateResult = apiDiscoverySettings.ApiAnnotationDiscoveryPredicate?.Invoke(clrType) ?? true;

            if (apiAnnotationDiscoveryPredicateResult == false)
            {
                return;
            }

            if (apiObjectTypeAttribute.Excluded)
            {
                apiPrecedenceStack.Push(ApiPrecedenceLevel.Annotation);
                apiSchemaBuilder.Exclude(clrType);
                apiPrecedenceStack.Pop();
                return;
            }

            IApiObjectTypeBuilder ApiObjectTypeConfiguration(IApiObjectTypeBuilder apiObjectTypeBuilder)
            {
                apiPrecedenceStack.Push(ApiPrecedenceLevel.Annotation);
                if (String.IsNullOrWhiteSpace(apiObjectTypeAttribute.Name) == false)
                {
                    apiObjectTypeBuilder.HasName(apiObjectTypeAttribute.Name);
                }

                if (String.IsNullOrWhiteSpace(apiObjectTypeAttribute.Description) == false)
                {
                    apiObjectTypeBuilder.HasDescription(apiObjectTypeAttribute.Description);
                }

                apiPrecedenceStack.Pop();

                return(apiObjectTypeBuilder);
            }

            apiPrecedenceStack.Push(ApiPrecedenceLevel.Annotation);
            apiSchemaBuilder.ApiObjectType(clrType, ApiObjectTypeConfiguration);
            apiPrecedenceStack.Pop();
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiNamingConvention Implementation
        public string Apply(string oldName, ApiConventionSettings apiConventionSettings)
        {
            if (String.IsNullOrWhiteSpace(oldName))
            {
                return(oldName);
            }

            var newName = oldName.Singularize(inputIsKnownToBePlural: false);

            return(newName);
        }
예제 #7
0
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiNamingConvention Implementation
        public string Apply(string oldName, ApiConventionSettings apiConventionSettings)
        {
            if (String.IsNullOrWhiteSpace(oldName))
            {
                return(oldName);
            }

            var newName = oldName.Camelize();

            return(newName);
        }
예제 #8
0
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiNamingConvention Implementation
        public string Apply(string oldName, ApiConventionSettings apiConventionSettings)
        {
            if (String.IsNullOrWhiteSpace(oldName))
            {
                return(oldName);
            }

            var newName = oldName.Transform(To.UpperCase);

            return(newName);
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeConvention Implementation
        public void Apply(IApiEnumerationTypeBuilder apiEnumerationTypeBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiEnumerationTypeBuilder != null);

            var clrEnumerationType = apiEnumerationTypeBuilder.ClrType;
            var clrEnumerationFieldInfoCollection = ClrEnumerationValueDiscoveryRules.GetClrEnumerationValues(clrEnumerationType);

            var apiEnumerationTypeConfiguration = (ApiEnumerationTypeConfiguration)apiEnumerationTypeBuilder;
            var apiPrecedenceStack = apiEnumerationTypeConfiguration.ApiPrecedenceStack;

            foreach (var clrEnumerationFieldInfo in clrEnumerationFieldInfoCollection)
            {
                HandleApiEnumerationValueAttribute(apiEnumerationTypeBuilder, apiPrecedenceStack, clrEnumerationFieldInfo);
            }
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeConvention Implementation
        public void Apply(IApiObjectTypeBuilder apiObjectTypeBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiObjectTypeBuilder != null);

            // Call ApiProperty method on all the discoverable CLR properties for the given CLR object type.
            var clrObjectType = apiObjectTypeBuilder.ClrType;
            var clrProperties = ClrPropertyDiscoveryRules.GetClrProperties(clrObjectType);

            foreach (var clrProperty in clrProperties)
            {
                var clrPropertyName = clrProperty.Name;
                var clrPropertyType = clrProperty.PropertyType;

                apiObjectTypeBuilder.ApiProperty(clrPropertyName, clrPropertyType);
            }
        }
예제 #11
0
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeConvention Implementation
        public void Apply(IApiEnumerationTypeBuilder apiEnumerationTypeBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiEnumerationTypeBuilder != null);

            // Call ApiEnumerationValue method on all the discoverable CLR enum values for the given CLR enum type.
            var clrEnumerationType = apiEnumerationTypeBuilder.ClrType;
            var clrEnumerationFieldInfoCollection = ClrEnumerationValueDiscoveryRules.GetClrEnumerationValues(clrEnumerationType);

            foreach (var clrFieldInfo in clrEnumerationFieldInfoCollection)
            {
                var clrName    = clrFieldInfo.Name;
                var clrOrdinal = (int)Enum.Parse(clrEnumerationType, clrName);

                apiEnumerationTypeBuilder.ApiEnumerationValue(clrName, clrOrdinal);
            }
        }
예제 #12
0
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeConvention Implementation
        public void Apply(IApiObjectTypeBuilder apiObjectTypeBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiObjectTypeBuilder != null);

            var clrObjectType             = apiObjectTypeBuilder.ClrType;
            var clrPropertyInfoCollection = ClrPropertyDiscoveryRules.GetClrProperties(clrObjectType);

            var apiObjectTypeConfiguration = (ApiObjectTypeConfiguration)apiObjectTypeBuilder;
            var apiPrecedenceStack         = apiObjectTypeConfiguration.ApiPrecedenceStack;

            foreach (var clrPropertyInfo in clrPropertyInfoCollection)
            {
                HandleApiPropertyAttribute(apiObjectTypeBuilder, apiPrecedenceStack, clrPropertyInfo);
                HandleApiIdentityAttribute(apiObjectTypeBuilder, apiPrecedenceStack, clrPropertyInfo);
                HandleApiRelationshipAttribute(apiObjectTypeBuilder, apiPrecedenceStack, clrPropertyInfo);
            }
        }
        // PUBLIC METHODS ///////////////////////////////////////////////////
        #region IApiObjectTypeConvention Implementation
        public void Apply(IApiObjectTypeBuilder apiObjectTypeBuilder, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiObjectTypeBuilder != null);

            // Try and discover relationship CLR properties of the CLR object type:
            var clrObjectType = apiObjectTypeBuilder.ClrType;
            var clrProperties = ClrPropertyDiscoveryRules.GetClrProperties(clrObjectType);

            foreach (var clrProperty in clrProperties)
            {
                var clrPropertyType = clrProperty.PropertyType;
                var apiTypeKind     = clrPropertyType.GetApiTypeKind(out var clrItemType);

                switch (apiTypeKind)
                {
                case ApiTypeKind.Collection:
                {
                    var apiItemTypeKind = clrItemType.GetApiTypeKind();
                    switch (apiItemTypeKind)
                    {
                    case ApiTypeKind.Object:
                    {
                        var clrPropertyName = clrProperty.Name;
                        apiObjectTypeBuilder.ApiRelationship(clrPropertyName, clrPropertyType);
                        break;
                    }
                    }
                    break;
                }

                case ApiTypeKind.Object:
                {
                    var clrPropertyName = clrProperty.Name;
                    apiObjectTypeBuilder.ApiRelationship(clrPropertyName, clrPropertyType);
                    break;
                }
                }
            }
        }
예제 #14
0
        // PRIVATE METHODS //////////////////////////////////////////////////
        #region Methods
        private void ApplyApiPropertyNameConventions(string clrName, IApiConventionSet apiConventionSet, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(clrName.SafeHasContent());
            Contract.Requires(apiConventionSet != null);

            var apiPropertyNameConventions = apiConventionSet?.ApiPropertyNameConventions;

            if (apiPropertyNameConventions == null)
            {
                return;
            }

            var apiPropertyNameConventionsCollection = apiPropertyNameConventions.SafeToReadOnlyCollection();

            if (!apiPropertyNameConventionsCollection.Any())
            {
                return;
            }

            var apiName = clrName;

            apiName = apiPropertyNameConventionsCollection.Aggregate(apiName, (current, apiNamingConvention) => apiNamingConvention.Apply(current, apiConventionSettings));

            this.HasName(apiName);
        }
        private void ApplyApiEnumerationTypeConventions(IApiConventionSet apiConventionSet, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(apiConventionSet != null);

            var apiEnumerationTypeConventions = apiConventionSet?.ApiEnumerationTypeConventions;

            if (apiEnumerationTypeConventions == null)
            {
                return;
            }

            foreach (var apiEnumerationTypeConvention in apiEnumerationTypeConventions)
            {
                apiEnumerationTypeConvention.Apply(this, apiConventionSettings);
            }
        }
        // PRIVATE METHODS //////////////////////////////////////////////////
        #region Methods
        private void ApplyApiEnumerationTypeNameConventions(Type clrEnumerationType, IApiConventionSet apiConventionSet, ApiConventionSettings apiConventionSettings)
        {
            Contract.Requires(clrEnumerationType != null);
            Contract.Requires(apiConventionSet != null);

            var apiEnumerationTypeNameConventions = apiConventionSet?.ApiEnumerationTypeNameConventions;

            if (apiEnumerationTypeNameConventions == null)
            {
                return;
            }

            var apiEnumerationTypeNameConventionsCollection = apiEnumerationTypeNameConventions.SafeToReadOnlyCollection();

            if (!apiEnumerationTypeNameConventionsCollection.Any())
            {
                return;
            }

            var apiName = clrEnumerationType.Name;

            apiName = apiEnumerationTypeNameConventionsCollection.Aggregate(apiName, (current, apiNamingConvention) => apiNamingConvention.Apply(current, apiConventionSettings));

            var apiEnumerationTypeBuilder = (IApiEnumerationTypeBuilder)this;

            apiEnumerationTypeBuilder.HasName(apiName);
        }