// // // // // $Revision: 3455 $ // using System; using System.Collections.Generic; using System.Globalization; using System.Text; namespace ICSharpCode.Core { /// /// This service is used to summarize important information /// about the state of the application when an exception occurs. /// public static class ApplicationStateInfoService { static readonly Dictionary stateGetters = new Dictionary(StringComparer.InvariantCulture); /// /// Registers a new method to be invoked to get information about the current state of the application. /// /// The title of the new state entry. /// The method to be invoked to get the state value. /// The is null. /// A state getter with the specified is already registered. public static void RegisterStateGetter(string title, StateGetter stateGetter) { lock(stateGetters) { stateGetters.Add(title, stateGetter); } } /// /// Determines whether a state getter with the specified title is already registered. /// /// The title to look for. /// true, if a state getter with the specified title is already registered, otherwise false. public static bool IsRegistered(string title) { lock(stateGetters) { return stateGetters.ContainsKey(title); } } /// /// Unregisters a state getter. /// /// The title of the state entry to remove. /// true if the specified title was found and removed, otherwise false. /// The is null. public static bool UnregisterStateGetter(string title) { lock(stateGetters) { return stateGetters.Remove(title); } } /// /// Gets a snapshot of the current application state information from all registered state getters. /// /// A dictionary with the titles and results of all registered state getters. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] public static IDictionary GetCurrentApplicationStateInfo() { Dictionary state = new Dictionary(stateGetters.Count, stateGetters.Comparer); lock(stateGetters) { foreach (KeyValuePair entry in stateGetters) { try { state.Add(entry.Key, entry.Value()); } catch (Exception ex) { state.Add(entry.Key, new StateGetterExceptionInfo(ex)); } } } return state; } /// /// Appends the current application state information from all registered state getters /// to the specified . /// /// The to append the state information to. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] public static void AppendFormatted(StringBuilder sb) { IFormattable f; Exception e; StateGetterExceptionInfo exceptionInfo; foreach (KeyValuePair entry in GetCurrentApplicationStateInfo()) { e = null; sb.Append(entry.Key); sb.Append(": "); if (entry.Value == null) { sb.AppendLine(""); } else { f = entry.Value as IFormattable; if (f != null) { try { sb.AppendLine(f.ToString(null, CultureInfo.InvariantCulture)); } catch (Exception ex) { sb.AppendLine("--> Exception thrown by IFormattable.ToString:"); e = ex; } } else { exceptionInfo = entry.Value as StateGetterExceptionInfo; if (exceptionInfo != null) { sb.AppendLine("--> Exception thrown by the state getter:"); e = exceptionInfo.Exception; } else { try { sb.AppendLine(entry.Value.ToString()); } catch (Exception ex) { sb.AppendLine("--> Exception thrown by ToString:"); e = ex; } } } } if (e != null) { sb.AppendLine(e.ToString()); } } } sealed class StateGetterExceptionInfo { readonly Exception exception; internal StateGetterExceptionInfo(Exception exception) { if (exception == null) throw new ArgumentNullException("exception"); this.exception = exception; } internal Exception Exception { get { return exception; } } public override string ToString() { return "StateGetterExceptionInfo: " + this.exception.ToString(); } } } /// /// A delegate used to get information about the current state of the application. /// public delegate object StateGetter(); }