public ModelDescription GetOrCreateModelDescription(Type modelType)
        {
            if (modelType == null)
            {
                throw new ArgumentNullException("modelType");
            }

            Type underlyingType = Nullable.GetUnderlyingType(modelType);

            if (underlyingType != null)
            {
                modelType = underlyingType;
            }

            ModelDescription modelDescription;
            string           modelName = ModelNameHelper.GetModelName(modelType);

            if (GeneratedModels.TryGetValue(modelName, out modelDescription))
            {
                if (modelType != modelDescription.ModelType)
                {
                    throw new InvalidOperationException(
                              String.Format(
                                  CultureInfo.CurrentCulture,
                                  "A model description could not be created. Duplicate model name '{0}' was found for types '{1}' and '{2}'. " +
                                  "Use the [ModelName] attribute to change the model name for at least one of the types so that it has a unique name.",
                                  modelName,
                                  modelDescription.ModelType.FullName,
                                  modelType.FullName));
                }

                return(modelDescription);
            }

            if (DefaultTypeDocumentation.ContainsKey(modelType))
            {
                return(GenerateSimpleTypeModelDescription(modelType));
            }

            if (modelType.IsEnum)
            {
                return(GenerateEnumTypeModelDescription(modelType));
            }

            if (modelType.IsGenericType)
            {
                Type[] genericArguments = modelType.GetGenericArguments();

                if (genericArguments.Length == 1)
                {
                    Type enumerableType = typeof(IEnumerable <>).MakeGenericType(genericArguments);
                    if (enumerableType.IsAssignableFrom(modelType))
                    {
                        return(GenerateCollectionModelDescription(modelType, genericArguments[0]));
                    }
                }
                if (genericArguments.Length == 2)
                {
                    Type dictionaryType = typeof(IDictionary <,>).MakeGenericType(genericArguments);
                    if (dictionaryType.IsAssignableFrom(modelType))
                    {
                        return(GenerateDictionaryModelDescription(modelType, genericArguments[0], genericArguments[1]));
                    }

                    Type keyValuePairType = typeof(KeyValuePair <,>).MakeGenericType(genericArguments);
                    if (keyValuePairType.IsAssignableFrom(modelType))
                    {
                        return(GenerateKeyValuePairModelDescription(modelType, genericArguments[0], genericArguments[1]));
                    }
                }
            }

            if (modelType.IsArray)
            {
                Type elementType = modelType.GetElementType();
                return(GenerateCollectionModelDescription(modelType, elementType));
            }

            if (modelType == typeof(NameValueCollection))
            {
                return(GenerateDictionaryModelDescription(modelType, typeof(string), typeof(string)));
            }

            if (typeof(IDictionary).IsAssignableFrom(modelType))
            {
                return(GenerateDictionaryModelDescription(modelType, typeof(object), typeof(object)));
            }

            if (typeof(IEnumerable).IsAssignableFrom(modelType))
            {
                return(GenerateCollectionModelDescription(modelType, typeof(object)));
            }

            return(GenerateComplexTypeModelDescription(modelType));
        }