/// <summary>
        /// Create a logger using the configured sinks, enrichers and minimum level.
        /// </summary>
        /// <returns>The logger.</returns>
        /// <remarks>To free resources held by sinks ahead of program shutdown,
        /// the returned logger may be cast to <see cref="IDisposable"/> and
        /// disposed.</remarks>
        public Logger CreateLogger()
        {
            if (_loggerCreated)
            {
                throw new InvalidOperationException("CreateLogger() was previously called and can only be called once.");
            }
            _loggerCreated = true;

            Action dispose = () =>
            {
                foreach (var disposable in _logEventSinks.OfType <IDisposable>())
                {
                    disposable.Dispose();
                }
            };

            ILogEventSink sink = new SafeAggregateSink(_logEventSinks);

            if (_filters.Any())
            {
                sink = new FilteringSink(sink, _filters);
            }

            var converter = new PropertyValueConverter(_maximumDestructuringDepth, _additionalScalarTypes, _additionalDestructuringPolicies);
            var processor = new MessageTemplateProcessor(converter);

            ILogEventEnricher enricher;

            switch (_enrichers.Count)
            {
            case 0:
                // Should be a rare case, so no problem making that extra interface dispatch.
                enricher = new EmptyEnricher();
                break;

            case 1:
                enricher = _enrichers[0];
                break;

            default:
                enricher = new SafeAggregateEnricher(_enrichers);
                break;
            }

            LevelOverrideMap overrideMap = null;

            if (_overrides.Count != 0)
            {
                overrideMap = new LevelOverrideMap(_overrides, _minimumLevel, _levelSwitch);
            }

            return(_levelSwitch == null ?
                   new Logger(processor, _minimumLevel, sink, enricher, dispose, overrideMap) :
                   new Logger(processor, _levelSwitch, sink, enricher, dispose, overrideMap));
        }
        /// <summary>
        /// Create a logger using the configured sinks, enrichers and minimum level.
        /// </summary>
        /// <returns>The logger.</returns>
        /// <remarks>To free resources held by sinks ahead of program shutdown,
        /// the returned logger may be cast to <see cref="IDisposable"/> and
        /// disposed.</remarks>
        /// <exception cref="InvalidOperationException">When the logger is already created</exception>
        public Logger CreateLogger()
        {
            if (_loggerCreated)
            {
                throw new InvalidOperationException("CreateLogger() was previously called and can only be called once.");
            }

            _loggerCreated = true;

            ILogEventSink sink = new SafeAggregateSink(_logEventSinks);

            var auditing = _auditSinks.Any();

            if (auditing)
            {
                sink = new AggregateSink(new[] { sink }.Concat(_auditSinks));
            }

            if (_filters.Any())
            {
                // A throwing filter could drop an auditable event, so exceptions in filters must be propagated
                // if auditing is used.
                sink = new FilteringSink(sink, _filters, auditing);
            }

            var converter = new PropertyValueConverter(
                _maximumDestructuringDepth,
                _maximumStringLength,
                _maximumCollectionCount,
                _additionalScalarTypes,
                _additionalDestructuringPolicies,
                auditing);
            var processor = new MessageTemplateProcessor(converter);

            ILogEventEnricher enricher;

            switch (_enrichers.Count)
            {
            case 0:
                // Should be a rare case, so no problem making that extra interface dispatch.
                enricher = new EmptyEnricher();
                break;

            case 1:
                enricher = _enrichers[0];
                break;

            default:
                // Enrichment failures are not considered blocking for auditing purposes.
                enricher = new SafeAggregateEnricher(_enrichers);
                break;
            }

            LevelOverrideMap overrideMap = null;

            if (_overrides.Count != 0)
            {
                overrideMap = new LevelOverrideMap(_overrides, _minimumLevel, _levelSwitch);
            }

            var disposableSinks = _logEventSinks.Concat(_auditSinks).OfType <IDisposable>().ToArray();

            void Dispose()
            {
                foreach (var disposable in disposableSinks)
                {
                    disposable.Dispose();
                }
            }

            return(_levelSwitch == null ?
                   new Logger(processor, _minimumLevel, sink, enricher, Dispose, overrideMap) :
                   new Logger(processor, _levelSwitch, sink, enricher, Dispose, overrideMap));
        }