private IEnumerable<PropertyDocumentation> CreatePropertyDocumentation(DtoDocumentationMetadata dtoDocumentationMetadata, String propertyPrefix)
        {
            if (propertyPrefix == null)
            {
                propertyPrefix = String.Empty;
            }

            IList<PropertyDocumentation> propertyDocumentation = new List<PropertyDocumentation>();
            var propertyDescriptors = TypeDescriptor.GetProperties(dtoDocumentationMetadata.Type)
                                                    .Cast<PropertyDescriptor>()
                                                    .Where(pi => pi.PropertyType.GetCustomAttributes(true)
                                                    .All(attribute =>
                                                            !(attribute is NonSerializedAttribute) &&
                                                            !(attribute is IgnoreDataMemberAttribute)))
                                                    .Select(pi => pi)
                                                    .ToList();

            foreach (var propertyDescriptor in propertyDescriptors)
            {
                var documentedProperty =
                    dtoDocumentationMetadata.PropertyDocumentationMetadata
                                            .SingleOrDefault(
                                                metadata =>
                                                metadata.Property.Name.Equals(propertyDescriptor.Name) &&
                                                metadata.Property.PropertyType.Equals(propertyDescriptor.PropertyType));

                if (!TypeHelper.CanConvertFromString(propertyDescriptor.PropertyType) &&
                    _WebApiDocumentationMetadata.DtoDocumentation.ContainsKey(propertyDescriptor.PropertyType))
                {
                    propertyDocumentation.Add(
                        new PropertyDocumentation(
                            GetPropertyNamePrefix(propertyDescriptor, propertyPrefix),
                            GetProperyTypeName(propertyDescriptor.PropertyType),
                            _WebApiDocumentationMetadata.DtoDocumentation[propertyDescriptor.PropertyType].Summary));

                    propertyDocumentation.AddRange(
                        CreatePropertyDocumentation(
                            _WebApiDocumentationMetadata.DtoDocumentation[propertyDescriptor.PropertyType],
                            String.Format("{0}{1}{2}", propertyPrefix, String.IsNullOrWhiteSpace(propertyPrefix) ? String.Empty : ".", propertyDescriptor.Name)));
                }
                else if (!TypeHelper.CanConvertFromString(propertyDescriptor.PropertyType) &&
                         GetEnumerableType(propertyDescriptor.PropertyType) != null &&
                         (propertyDescriptor.PropertyType.IsGenericType && 
                          _WebApiDocumentationMetadata.DtoDocumentation.ContainsKey(propertyDescriptor.PropertyType.GetGenericArguments().First())))
                {
                    var genericPropertyType = propertyDescriptor.PropertyType.GetGenericArguments().First();

                    propertyDocumentation.Add(
                        new PropertyDocumentation(
                            GetPropertyNamePrefix(propertyDescriptor, propertyPrefix),
                            GetProperyTypeName(propertyDescriptor.PropertyType),
                            _WebApiDocumentationMetadata.DtoDocumentation[genericPropertyType].Summary));

                    if (propertyPrefix.Contains(propertyDescriptor.Name) || genericPropertyType.Equals(dtoDocumentationMetadata.Type))
                    {
                        continue; // Prevent circular dependencies.
                    }

                    propertyDocumentation.AddRange(
                        CreatePropertyDocumentation(
                            _WebApiDocumentationMetadata.DtoDocumentation[genericPropertyType],
                            String.Format("{0}{1}{2}", propertyPrefix, String.IsNullOrWhiteSpace(propertyPrefix) ? String.Empty : ".", propertyDescriptor.Name)));
                }
                else
                {
                    propertyDocumentation.Add(
                        new PropertyDocumentation(
                            GetPropertyNamePrefix(propertyDescriptor, propertyPrefix),
                            GetProperyTypeName(propertyDescriptor.PropertyType),
                            documentedProperty == null ? String.Empty : documentedProperty.Description));
                }
            }

            return propertyDocumentation;
        }
        private Object CreateResponseContentExample(DtoDocumentationMetadata dtoDocumentationMetadata)
        {
            // Create an example DTO based off AutoFixture / ObjectHydrator conventions to be used as reference if properties aren't documented.
            var exampleObject = CreateInstanceOfType(dtoDocumentationMetadata.Type);

            IDictionary<String, Object> responseExample = new ExpandoObject();
            var propertyDescriptors = TypeDescriptor.GetProperties(dtoDocumentationMetadata.Type);
            var dtoProperties =
                dtoDocumentationMetadata.Type
                                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                        .Where(pi => pi.GetCustomAttributes(true)
                                                       .All(
                                                           attribute =>
                                                           !(attribute is NonSerializedAttribute) &&
                                                           !(attribute is IgnoreDataMemberAttribute)))
                                        .Select(pi => propertyDescriptors[pi.Name]);

            foreach (var propertyDescriptor in dtoProperties)
            {
                if (!TypeHelper.CanConvertFromString(propertyDescriptor.PropertyType) &&
                    _WebApiDocumentationMetadata.DtoDocumentation.ContainsKey(propertyDescriptor.PropertyType))
                {
                    responseExample[propertyDescriptor.Name] =
                        CreateResponseContentExample(_WebApiDocumentationMetadata.DtoDocumentation[propertyDescriptor.PropertyType]);
                }
                else
                {
                    responseExample[propertyDescriptor.Name] = propertyDescriptor.GetValue(exampleObject);
                }
            }

            return responseExample;
        }
        private Object CreateRequestBodyExample(HttpActionDescriptor httpActionDescriptor, DtoDocumentationMetadata dtoDocumentationMetadata)
        {
            // Create an example DTO based off AutoFixture / ObjectHydrator conventions to be used as reference if properties aren't documented.
            var exampleObject = CreateInstanceOfType(dtoDocumentationMetadata.Type);

            IDictionary<String, Object> requestBodyExample = new ExpandoObject();
            foreach (DtoPropertyDocumentationMetadata dtoProperty in dtoDocumentationMetadata.PropertyDocumentationMetadata)
            {
                if (!TypeHelper.CanConvertFromString(dtoProperty.Property.PropertyType) &&
                    _WebApiDocumentationMetadata.DtoDocumentation.ContainsKey(dtoProperty.Property.PropertyType))
                {
                    requestBodyExample[dtoProperty.Property.Name] =
                        CreateRequestBodyExample(httpActionDescriptor, _WebApiDocumentationMetadata.DtoDocumentation[dtoProperty.Property.PropertyType]);
                }
                else if (!httpActionDescriptor.SupportedHttpMethods.Intersect(dtoProperty.ExcludedMethods ?? Enumerable.Empty<HttpMethod>()).Any())
                {
                    if (_WebApiDocumentationMetadata.Settings
                        .RequestBuilderConventions
                        .Any(c => !c.IncludeProperty(
                            httpActionDescriptor.SupportedHttpMethods,
                            dtoDocumentationMetadata.Type.GetProperty(dtoProperty.Property.Name),
                            dtoDocumentationMetadata.Type)))
                    {
                        continue;
                    }

                    var propertyDocumentationMetadata =
                    dtoDocumentationMetadata.PropertyDocumentationMetadata
                                            .SingleOrDefault(pdm => pdm.Property.Equals(dtoProperty.Property) && pdm.ExampleValue != null);

                    if (propertyDocumentationMetadata != null)
                    {
                        requestBodyExample[dtoProperty.Property.Name] = propertyDocumentationMetadata.ExampleValue;
                    }
                    else
                    {
                        requestBodyExample[dtoProperty.Property.Name] = dtoProperty.Property.GetValue(exampleObject);
                    }
                }
            }

            return requestBodyExample;
        }