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

			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 (DocumentationProvider != null)
					{
						propertyModel.Documentation = DocumentationProvider.GetDocumentation(property);
					}

					GenerateAnnotations(property, propertyModel);
					complexModelDescription.Properties.Add(propertyModel);
					propertyModel.TypeDescription = 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 (DocumentationProvider != null)
					{
						propertyModel.Documentation = DocumentationProvider.GetDocumentation(field);
					}

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

			return complexModelDescription;
		}
        private static ParameterDescription AddParameterDescription(HelpPageApiModel apiModel,
			ApiParameterDescription apiParameter, ModelDescription typeDescription)
        {
            ParameterDescription parameterDescription = new ParameterDescription
            {
                Name = apiParameter.Name,
                Documentation = apiParameter.Documentation,
                TypeDescription = typeDescription,
            };

            apiModel.UriParameters.Add(parameterDescription);
            return parameterDescription;
        }
		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);
			}
		}