示例#1
0
        /// <summary>
        /// Allows you to create a deep and detailed representation of an object tree, including properties of the objects.
        /// Useful for debugging and reporting scenarios where <see cref="Object.ToString"/> simply does not give enough information.
        /// </summary>
        /// <remarks>
        /// The maximum object tree depth is limited, to avoid outputting too deep (or potentially infinite) hierarchies.
        /// Repeated objects are referred to by object ID, not output multiple times, to make the output more concise.
        ///
        /// <para>Not everything is displayed - there is some fitering and transformation done. The specifics are not listed here.
        /// Some types have special handing to make them more meaningful (e.g. System.String, IEnumerable).</para>
        ///
        /// <para>Generally, the data returned varies per type and may change in the future.
        /// Do not rely on the output remaining same in future versions, even for the same object.</para>
        /// </remarks>
        public static string ToDebugString(this HelpersContainerClasses.Debug container, object o)
        {
            Helpers.Argument.ValidateIsNotNull(o, nameof(o));

            StringBuilder s = new StringBuilder();
            var           visitedObjects = new List <object>();

            CreateDebugString(o, s, 0, visitedObjects);

            return(s.ToString());
        }
示例#2
0
        /// <summary>
        /// Just to state what exactly we are dealing with when an app starts up.
        /// </summary>
        public static string GetLoadedAssembliesInfodump(this HelpersContainerClasses.Debug container)
        {
            var sb = new StringBuilder();

            sb.AppendLine("Loaded assemblies:");

            var loadedAssemblyNames = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName());

            // We filter out system assemblies because they are boring.
            foreach (var assemblyName in loadedAssemblyNames
                     .Where(a => !a.Name.StartsWith("System."))
                     .OrderBy(a => a.Name))
            {
                sb.AppendLine($"{assemblyName.Name} {assemblyName.Version}");
            }

            return(sb.ToString());
        }
示例#3
0
        /// <summary>
        /// Gets the Message properties of an exception and all its inner exceptions and all the exception type names.
        ///
        /// Useful if you have top-level exceptions with pointless generic messages but also want to see deeper
        /// without spamming out the entire call stack information for every exception.
        /// </summary>
        public static string GetAllExceptionMessages(this HelpersContainerClasses.Debug container, Exception ex)
        {
            var sb = new StringBuilder();

            var indentLevel = 0;

            void AppendException(Exception e)
            {
                if (e is AggregateException aex)
                {
                    if (aex.InnerExceptions.Count == 1)
                    {
                        AppendException(aex.InnerException);
                        return;
                    }

                    sb.AppendLine($"AggregateException");

                    indentLevel++;

                    foreach (var inner in aex.InnerExceptions)
                    {
                        sb.AppendLine("Aggregate member:");
                        AppendException(inner);
                    }

                    indentLevel--;
                }
                else
                {
                    sb.AppendLine($"{e.Message} ({e.GetType().Name})");

                    if (e.InnerException != null)
                    {
                        AppendException(e.InnerException);
                    }
                }
            }

            AppendException(ex);

            // We don't want the last newline, thanks.
            return(sb.ToString().Trim('\r', '\n'));
        }