// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
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();
}