/// <summary>
 /// Creates a <see cref="Validator"/> which performs a simple validation for the specified
 /// <see cref="ConfigurationRequirementType"/> <paramref name="type"/>.
 /// </summary>
 /// <param name="type">
 /// The <see cref="ConfigurationRequirementType"/> to perform validation using.
 /// </param>
 /// <param name="additionalValidation">
 /// A <see cref="Validator"/> which accepts the instance <see cref="object"/> being validated. This
 /// <paramref name="additionalValidation"/> will only be invoked if the <see cref="object"/> passes the
 /// default validation logic.
 /// </param>
 /// <returns>
 /// A simple <see cref="Validator"/> with the default validation logic.
 /// </returns>
 public static Validator CreateSimpleValidator(
     ConfigurationRequirementType type,
     Validator additionalValidation = null)
 {
     return((instance, requirement, dependentMappings) => ConfigurationRequirement.SimpleValidator(
                type,
                instance,
                requirement,
                dependentMappings,
                additionalValidation));
 }
 /// <summary>
 /// Creates a new <see cref="ConfigurationRequirement"/> of type
 /// <see cref="ConfigurationRequirementType.Uri"/>.
 /// </summary>
 /// <param name="name">
 /// The name of the <see cref="ConfigurationRequirement"/>.
 /// </param>
 /// <param name="description">
 /// The description of the <see cref="ConfigurationRequirement"/>.
 /// </param>
 /// <param name="isOptional">
 /// Indicates whether the <see cref="ConfigurationRequirement"/> is optional.
 /// </param>
 /// <param name="collectionInfo">
 /// The <see cref="CollectionInfo"/> describing this <see cref="ConfigurationRequirement"/>.
 /// When <see langword="null"/>, indicates that this <see cref="ConfigurationRequirement"/> is not a
 /// collection.
 /// </param>
 /// <param name="dependsOn">
 /// A collection of <see cref="IConfigurationRequirement"/>s which this <see cref="ConfigurationRequirement"/>
 /// must be supplied alongside.
 /// </param>
 /// <param name="exclusiveWith">
 /// A collection of <see cref="IConfigurationRequirement"/>s which this <see cref="ConfigurationRequirement"/>
 /// must not be supplied alongside with.
 /// </param>
 /// <param name="additionalValidation">
 /// A <see cref="Validator"/> which accepts the instance <see cref="object"/> being validated. This
 /// <paramref name="additionalValidation"/> will only be invoked if the <see cref="object"/> passes the
 /// default validation logic.
 /// </param>
 /// <returns>
 /// A <see cref="ConfigurationRequirement"/> of type <see cref="ConfigurationRequirementType.Uri"/> with the
 /// supplied properties.
 /// </returns>
 public static IConfigurationRequirement Uri(
     string name,
     string description,
     bool isOptional = false,
     CollectionInfo collectionInfo = null,
     IEnumerable <IConfigurationRequirement> dependsOn     = null,
     IEnumerable <IConfigurationRequirement> exclusiveWith = null,
     Validator additionalValidation = null)
 {
     return(new ConfigurationRequirement(
                name,
                description,
                ConfigurationRequirementType.Uri,
                isOptional,
                ConfigurationRequirement.CreateSimpleValidator(
                    ConfigurationRequirementType.Uri,
                    additionalValidation),
                collectionInfo,
                dependsOn,
                exclusiveWith));
 }
        /// <summary>
        /// Instantiates a new <see cref="ConfigurationRequirement"/> instance using the supplied parameters.
        /// </summary>
        /// <param name="name">
        /// The name of the <see cref="ConfigurationRequirement"/>.
        /// </param>
        /// <param name="description">
        /// The description of the <see cref="ConfigurationRequirement"/>.
        /// </param>
        /// <param name="ofType">
        /// The <see cref="ConfigurationRequirementType"/> of the <see cref="ConfigurationRequirement"/>.
        /// </param>
        /// <param name="isOptional">
        /// Indicates whether this <see cref="ConfigurationRequirement"/> is optional.
        /// </param>
        /// <param name="validator">
        /// Validates <see cref="object"/>s to determine if they satisfy the <see cref="ConfigurationRequirement"/>.
        /// </param>
        /// <param name="collectionInfo">
        /// The <see cref="CollectionInfo"/> describing this <see cref="ConfigurationRequirement"/>.
        /// When <see langword="null"/>, indicates that this <see cref="ConfigurationRequirement"/> is not a
        /// collection.
        /// </param>
        /// <param name="dependsOn">
        /// A collection of <see cref="IConfigurationRequirement"/>s which this <see cref="ConfigurationRequirement"/>
        /// must be supplied alongside.
        /// </param>
        /// <param name="exclusiveWith">
        /// A collection of <see cref="IConfigurationRequirement"/>s which this <see cref="ConfigurationRequirement"/>
        /// must not be supplied alongside with.
        /// </param>
        public ConfigurationRequirement(
            string name,
            string description,
            ConfigurationRequirementType ofType,
            bool isOptional,
            Validator validator,
            CollectionInfo collectionInfo = null,
            IEnumerable <IConfigurationRequirement> dependsOn     = null,
            IEnumerable <IConfigurationRequirement> exclusiveWith = null)
        {
            ConfigurationRequirement.ThrowIfBadString(name, nameof(name));
            ConfigurationRequirement.ThrowIfBadString(description, nameof(description));
            this.Name           = name;
            this.Description    = description;
            this.OfType         = ofType;
            this.IsOptional     = isOptional;
            this.CollectionInfo = collectionInfo;
            this.DependsOn      = dependsOn ?? new IConfigurationRequirement[0];
            this.ExclusiveWith  = exclusiveWith ?? new IConfigurationRequirement[0];

            this.validator      = validator ?? throw new ArgumentNullException(nameof(validator));
            this.cachedToString = null;
        }