/// <summary>
        /// Constructs <see cref="Switch"/> instances for the current
        /// `system.diagnostics/switches` configuration.
        /// </summary>
        /// <param name="configurationSection"></param>
        /// <returns></returns>
        private static IDictionary <string, Switch> InstantiateSwitches(
            SystemDiagnosticsConfigurationSection configurationSection)
        {
            var switches = new Dictionary <string, Switch>(StringComparer.OrdinalIgnoreCase);

            if (configurationSection.Switches != null)
            {
                foreach (SwitchElement switchElement in configurationSection.Switches)
                {
                    // multiple rules dictate switch type
                    var @switch = default(Switch);
                    if (bool.TryParse(switchElement.Value, out bool boolValue))
                    {
                        // if value is a `bool`, use `BooleanSwitch`
                        @switch = new BooleanSwitch(switchElement.Name, "", switchElement.Value);
                    }
                    else if (Enum.TryParse(switchElement.Value, out TraceLevel traceLevel))
                    {
                        // if value is a `TraceLevel`, use `TraceSwitch`
                        @switch = new TraceSwitch(switchElement.Name, "", switchElement.Value);
                    }
                    else
                    {
                        throw new Exception(
                                  $"Unsupported Value '{switchElement.Value}' for Switch '{switchElement.Name}'.");
                    }
                    switches.Add(switchElement.Name, @switch);
                }
            }
            return(switches);
        }
 /// <summary>
 /// Configure `System.Diagnostics` using specified <paramref name="systemDiagnosticsConfigurationSection"/>.
 /// </summary>
 /// <param name="systemDiagnosticsConfigurationSection"></param>
 internal static ConfigurationSection Configure(
     SystemDiagnosticsConfigurationSection systemDiagnosticsConfigurationSection)
 {
     if (systemDiagnosticsConfigurationSection != null)
     {
         _switches  = InstantiateSwitches(systemDiagnosticsConfigurationSection);
         _listeners = InstantiateSharedListeners(systemDiagnosticsConfigurationSection);
         _sources   = InstantiateSources(systemDiagnosticsConfigurationSection, _switches, _listeners);
         InitializeTraceTraceListeners(systemDiagnosticsConfigurationSection);
     }
     return(systemDiagnosticsConfigurationSection);
 }
 /// <summary>
 /// Initialize the Trace Listeners assigned to <see cref="System.Diagnostics.Trace.Listeners"/>.
 /// </summary>
 /// <param name="systemDiagnosticsConfigurationSection"></param>
 private static void InitializeTraceTraceListeners(
     SystemDiagnosticsConfigurationSection systemDiagnosticsConfigurationSection)
 {
     // TODO: support `<clear/>`
     foreach (TraceListenerElement listenerElement in systemDiagnosticsConfigurationSection.Trace.Listeners)
     {
         if (_listeners.TryGetValue(listenerElement.Name, out TraceListener traceListener))
         {
             Trace.Listeners.Remove(listenerElement.Name);
             Trace.Listeners.Add(traceListener);
         }
     }
 }
        /// <summary>
        /// Constructs shared <see cref="TraceListener"/> instances for the
        /// current `system.diagnostics/sharedListeners` configuration.
        /// </summary>
        /// <param name="configurationSection"></param>
        /// <returns></returns>
        private static IDictionary <string, TraceListener> InstantiateSharedListeners(
            SystemDiagnosticsConfigurationSection configurationSection)
        {
            var sharedListeners = new Dictionary <string, TraceListener>(StringComparer.OrdinalIgnoreCase);

            if (configurationSection.SharedListeners != null)
            {
                foreach (TraceListenerElement traceListenerElement in configurationSection.SharedListeners)
                {
                    try
                    {
                        var traceListener = InstantiateTraceListener(traceListenerElement);
                        sharedListeners.Add(traceListener.Name, traceListener);
                    }
                    catch (Exception ex)
                    {
                        ex.Log();
                    }
                }
            }

            return(sharedListeners);
        }
        /// <summary>
        /// Constructs <see cref="TraceSource"/> instances for the current
        /// `system.diagnostics/trace` configuration.
        /// </summary>
        /// <param name="systemDiagnosticsConfigurationSection"></param>
        /// <param name="switches"></param>
        /// <param name="sharedListeners"></param>
        /// <returns></returns>
        private static IDictionary <string, TraceSource> InstantiateSources(
            SystemDiagnosticsConfigurationSection systemDiagnosticsConfigurationSection,
            IDictionary <string, Switch> switches,
            IDictionary <string, TraceListener> sharedListeners)
        {
            // TODO: `system.diagnostics/switches` are not properly evaluated
            //       at run-time, and cannot be used to control
            //       `system.diagnostics/sources`, although this bootstrapper
            //       does make an attempt to transpose switch values and most
            //       developers will not know the difference.
            var sources = new Dictionary <string, TraceSource>(StringComparer.OrdinalIgnoreCase);

            if (systemDiagnosticsConfigurationSection.Sources != null)
            {
                foreach (SourceElement sourceElement in systemDiagnosticsConfigurationSection.Sources)
                {
                    var traceSource = new TraceSource(sourceElement.Name);
                    var switchValue = !string.IsNullOrWhiteSpace(sourceElement.SwitchValue)
                                    ? sourceElement.SwitchValue
                                    : $"{SourceLevels.All}";
                    if (!string.IsNullOrWhiteSpace(sourceElement.SwitchType))
                    {
                        traceSource.Switch =
                            Activator.CreateInstance(
                                Type.GetType(sourceElement.SwitchType),
                                sourceElement.SwitchName ?? $"{sourceElement.Name}",
                                switchValue)
                            as SourceSwitch;
                    }
                    else if (switches.TryGetValue(sourceElement.SwitchName, out Switch @switch))
                    {
                        if (@switch is TraceSwitch traceSwitch)
                        {
                            traceSource.Switch = new SourceSwitch(
                                sourceElement.SwitchName,
                                Enum.Parse(typeof(SourceLevels), Convert.ToString(traceSwitch.Level)).ToString());
                        }
                        else if (@switch is BooleanSwitch booleanSwitch)
                        {
                            traceSource.Switch = new SourceSwitch(
                                sourceElement.SwitchName,
                                booleanSwitch.Enabled
                                    ? $"{SourceLevels.All}"
                                    : $"{SourceLevels.Off}");
                        }
                        else
                        {
                            // TODO: need to look through reference source
                            //       and understand how switch configuration
                            //       is done in net45 -- this behavior here
                            //       is actually incorrect (and the behavior
                            //       above is also not entirely proper, but
                            //       does allow the use of switches as most
                            //       developers would expect them to work via
                            //       the config file.)
                            traceSource.Switch = new SourceSwitch(
                                sourceElement.SwitchName,
                                switchValue);
                        }
                    }
                    else
                    {
                        traceSource.Switch.Level = Enum.TryParse(switchValue, out SourceLevels sourceLevel)
                            ? sourceLevel
                            : SourceLevels.All;
                    }

                    foreach (TraceListenerElement traceListenerElement in sourceElement.Listeners)
                    {
                        traceSource.Listeners.Remove(traceListenerElement.Name);
                        if (string.IsNullOrWhiteSpace(traceListenerElement.TypeName))
                        {
                            if (sharedListeners.TryGetValue(traceListenerElement.Name, out TraceListener traceListener))
                            {
                                traceSource.Listeners.Add(traceListener);
                            }
                            else
                            {
                                throw new Exception(
                                          $"Source '{sourceElement.Name}' references shared listener '{traceListenerElement.Name}' which does not exist in `<sharedListeners/>`.");
                            }
                        }
                        else
                        {
                            traceSource.Listeners.Add(
                                InstantiateTraceListener(traceListenerElement));
                        }
                    }
                    sources.Add(traceSource.Name, traceSource);
                }
            }
            return(sources);
        }