private ModelDescription GenerateComplexTypeModelDescription(Type modelType)
        {
            var complexModelDescription = new ComplexTypeModelDescription
                                              {
                                                  Name =
                                                      ModelNameHelper.GetModelName(
                                                          modelType), 
                                                  ModelType = modelType, 
                                                  Documentation =
                                                      this.CreateDefaultDocumentation(
                                                          modelType)
                                              };

            this.GeneratedModels.Add(complexModelDescription.Name, complexModelDescription);
            var hasDataContractAttribute = modelType.GetCustomAttribute<DataContractAttribute>() != null;
            var properties = modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var property in properties)
            {
                if (ShouldDisplayMember(property, hasDataContractAttribute))
                {
                    var propertyModel = new ParameterDescription
                                            {
                                                Name =
                                                    GetMemberName(
                                                        property, 
                                                        hasDataContractAttribute)
                                            };

                    if (this.DocumentationProvider != null)
                    {
                        propertyModel.Documentation = this.DocumentationProvider.GetDocumentation(property);
                    }

                    this.GenerateAnnotations(property, propertyModel);
                    complexModelDescription.Properties.Add(propertyModel);
                    propertyModel.TypeDescription = this.GetOrCreateModelDescription(property.PropertyType);
                }
            }

            var fields = modelType.GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (var field in fields)
            {
                if (ShouldDisplayMember(field, hasDataContractAttribute))
                {
                    var propertyModel = new ParameterDescription
                                            {
                                                Name = GetMemberName(field, hasDataContractAttribute)
                                            };

                    if (this.DocumentationProvider != null)
                    {
                        propertyModel.Documentation = this.DocumentationProvider.GetDocumentation(field);
                    }

                    complexModelDescription.Properties.Add(propertyModel);
                    propertyModel.TypeDescription = this.GetOrCreateModelDescription(field.FieldType);
                }
            }

            return complexModelDescription;
        }
        private void GenerateAnnotations(MemberInfo property, ParameterDescription propertyModel)
        {
            var annotations = new List<ParameterAnnotation>();

            var attributes = property.GetCustomAttributes();
            foreach (var attribute in attributes)
            {
                Func<object, string> textGenerator;
                if (this.AnnotationTextGenerator.TryGetValue(attribute.GetType(), out textGenerator))
                {
                    annotations.Add(
                        new ParameterAnnotation
                            {
                                AnnotationAttribute = attribute, 
                                Documentation = textGenerator(attribute)
                            });
                }
            }

            // Rearrange the annotations
            annotations.Sort(
                (x, y) =>
                    {
                        // Special-case RequiredAttribute so that it shows up on top
                        if (x.AnnotationAttribute is RequiredAttribute)
                        {
                            return -1;
                        }

                        if (y.AnnotationAttribute is RequiredAttribute)
                        {
                            return 1;
                        }

                        // Sort the rest based on alphabetic order of the documentation
                        return string.Compare(x.Documentation, y.Documentation, StringComparison.OrdinalIgnoreCase);
                    });

            foreach (var annotation in annotations)
            {
                propertyModel.Annotations.Add(annotation);
            }
        }