/// <summary>
 /// Initializes a new instance of the <see cref="CompositeSecretProvider"/> class.
 /// </summary>
 /// <param name="secretProviderSources">The sequence of all available registered secret provider registrations.</param>
 /// <param name="criticalExceptionFilters">The sequence of all available registered critical exception filters.</param>
 /// <param name="auditingOptions">The customized options to configure the auditing of the secret store.</param>
 /// <exception cref="ArgumentNullException">Thrown when the <paramref name="secretProviderSources"/> or <paramref name="criticalExceptionFilters"/> or <paramref name="auditingOptions"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentException">Thrown when the <paramref name="secretProviderSources"/> of the <paramref name="criticalExceptionFilters"/> contains any <c>null</c> values.</exception>
 public CompositeSecretProvider(
     IEnumerable <SecretStoreSource> secretProviderSources,
     IEnumerable <CriticalExceptionFilter> criticalExceptionFilters,
     SecretStoreAuditingOptions auditingOptions)
     : this(secretProviderSources, criticalExceptionFilters, auditingOptions, NullLogger <CompositeSecretProvider> .Instance)
 {
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="CompositeSecretProvider"/> class.
        /// </summary>
        /// <param name="secretProviderSources">The sequence of all available registered secret provider registrations.</param>
        /// <param name="criticalExceptionFilters">The sequence of all available registered critical exception filters.</param>
        /// <param name="auditingOptions">The customized options to configure the auditing of the secret store.</param>
        /// <param name="logger">The logger instance to write diagnostic messages during the retrieval of secrets via the registered <paramref name="secretProviderSources"/>.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="secretProviderSources"/> or <paramref name="criticalExceptionFilters"/> or <paramref name="auditingOptions"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="secretProviderSources"/> of the <paramref name="criticalExceptionFilters"/> contains any <c>null</c> values.</exception>
        public CompositeSecretProvider(
            IEnumerable <SecretStoreSource> secretProviderSources,
            IEnumerable <CriticalExceptionFilter> criticalExceptionFilters,
            SecretStoreAuditingOptions auditingOptions,
            ILogger <CompositeSecretProvider> logger)
        {
            Guard.NotNull(secretProviderSources, nameof(secretProviderSources), "Requires a series of registered secret provider registrations to retrieve secrets");
            Guard.NotNull(criticalExceptionFilters, nameof(criticalExceptionFilters), "Requires a series of registered critical exception filters to determine if a thrown exception is critical");
            Guard.NotNull(auditingOptions, nameof(auditingOptions), "Requires a set of options to configure the auditing of the secret store");
            Guard.For <ArgumentException>(() => secretProviderSources.Any(source => source is null), "Requires all registered secret provider registrations to be not 'null'");
            Guard.For <ArgumentException>(() => criticalExceptionFilters.Any(filter => filter is null), "Requires all registered critical exception filters to be not 'null'");

            _secretProviders          = secretProviderSources;
            _criticalExceptionFilters = criticalExceptionFilters;
            _auditingOptions          = auditingOptions;
            _logger = logger ?? NullLogger <CompositeSecretProvider> .Instance;
        }
        private static IDictionary <string, Lazy <ISecretProvider> > CreateGroupedSecretProviders(
            IEnumerable <SecretStoreSource> secretProviders,
            IEnumerable <CriticalExceptionFilter> criticalExceptionFilters,
            SecretStoreAuditingOptions auditingOptions,
            ILogger <CompositeSecretProvider> logger)
        {
            return(secretProviders
                   .Where(source => source.Options.Name != null)
                   .GroupBy(source => source.Options.Name)
                   .ToDictionary(group => group.Key, group =>
            {
                return new Lazy <ISecretProvider>(() =>
                {
                    if (group.Count() == 1)
                    {
                        SecretStoreSource source = group.First();
                        return source.CachedSecretProvider ?? source.SecretProvider;
                    }

                    return new CompositeSecretProvider(group, criticalExceptionFilters, auditingOptions, logger);
                });
            }));
        }