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

			GeneratedModels.Add(complexModelDescription.Name, complexModelDescription);
			bool hasDataContractAttribute = modelType.GetCustomAttribute<DataContractAttribute>() != null;
			PropertyInfo[] properties = modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
			foreach (PropertyInfo property in properties)
			{
				if (ShouldDisplayMember(property, hasDataContractAttribute))
				{
					ParameterDescription 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);
				}
			}

			FieldInfo[] fields = modelType.GetFields(BindingFlags.Public | BindingFlags.Instance);
			foreach (FieldInfo field in fields)
			{
				if (ShouldDisplayMember(field, hasDataContractAttribute))
				{
					ParameterDescription 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)
		{
			List<ParameterAnnotation> annotations = new List<ParameterAnnotation>();

			IEnumerable<Attribute> attributes = property.GetCustomAttributes();
			foreach (Attribute 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 (ParameterAnnotation annotation in annotations)
			{
				propertyModel.Annotations.Add(annotation);
			}
		}