public ModelDescription Generate(Type modelType, ModelDescriptionGenerator generator)
        {
            var provider = new DocProvider();
            
            var complexModelDescription = new ComplexTypeModelDescription
            {
                Name = ModelNameHelper.GetModelName(modelType),
                ModelType = modelType,
                Documentation = generator.CreateDefaultDocumentation(modelType),
                ParameterDocumentation = provider.GetDocumentation(modelType)
            };

            generator.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 (!ModelDescriptionGenerator.ShouldDisplayMember(property, hasDataContractAttribute)) continue;
                var propertyModel = new ParameterDescription
                {
                    Name = GetMemberName(property, hasDataContractAttribute)
                };

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

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

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

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

                complexModelDescription.Properties.Add(propertyModel);
                propertyModel.TypeDescription = generator.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 (_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);
            }
        }
        public static ParameterDescription AddParameterDescription(
            this Collection<ParameterDescription> uriParameters,
            ApiParameterDescription apiParameter, ModelDescription typeDescription)
        {
            var parameterDescription = new ParameterDescription
            {
                Name = apiParameter.Name,
                Documentation = apiParameter.Documentation,
                TypeDescription = typeDescription,
            };

            uriParameters.Add(parameterDescription);
            return parameterDescription;
        }