// FileSystemInfo Parent and Root properties are examples of "bloat" properties and should be dumped with ToString Dictionary<string, bool> data = new Dictionary<string, bool>(); data["Parent"] = false; data["Root"] = false; s[typeof(FileSystemInfo)] = data; return s; } private readonly StringBuilder _out = new StringBuilder(10000); readonly Dictionary<object, int> _usedMap = new Dictionary<object, int>(new ReferenceComparer()); private int _counter = 0; void process2(string name, Type t, object o, int depth) { string typeName = GetFriendlyTypeName(t, _settings.UseFullClassNames); _out.Append(new string(' ', depth * 2)); if (!string.IsNullOrEmpty(name)) _out.Append(name + " = "); _out.Append("(" + typeName + ") "); if (o == null) { _out.Append("<null>"); return; } if ((t != typeof(string) && (o is string)) || _settings.MaxDepth <= depth) { _out.Append("\"" + toEscapedString(o) + "\" /* ToString */"); return; } if (t == typeof(string) || (o is string)) { _out.Append("\"" + toEscapedString(o) + "\""); return; } BindingFlags flags = BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public; if (_settings.DisplayPrivate) flags |= BindingFlags.NonPublic; PropertyInfo[] props = t.GetProperties(flags | BindingFlags.GetProperty); FieldInfo[] fi = t.GetFields(flags); if (t.IsPrimitive || t.IsEnum || (t.IsValueType && props.Length == 0 && fi.Length == 0) || s_bloatTypes.ContainsKey(t.FullName) || t == typeof(decimal)) { if ((t == typeof(int)) || (t == typeof(byte)) || (t == typeof(uint)) || t == typeof(long) || t == typeof(ulong)) _out.AppendFormat(" {0} (0x{0:x})", o); else if (t == typeof(DateTime) || t == typeof(DateTime?)) _out.AppendFormat("{0:o} ({1})", o, ((DateTime)o).Kind); else if (t == typeof(Guid)) _out.Append(((Guid)o).ToString("B")); else if (t == typeof(bool)) _out.Append(((bool)o) ? "true" : "false"); else if (t.IsEnum) _out.AppendFormat("[{0}] /* 0x{0:x} */", o); else _out.AppendFormat("[{0}]", toEscapedString(o)); return; } if (t.IsClass) { int id; if (_usedMap.TryGetValue(o, out id)) { _out.AppendFormat("<see #{0}, {1:x8} above>", id, o.GetHashCode()); return; } _usedMap[o] = ++_counter; } if (t.IsArray && ((Array)o).Rank == 1) { Array arr; if (t.IsArray) arr = (o as Array); else arr = t.GetMethod("ToArray").Invoke(o, new object[] { }) as Array; processArray(t, arr, depth); } else if (o as IEnumerable != null) { writeBrace(o); processEnumerables(o as IEnumerable, depth); } else { writeBrace(o); Dictionary<string, bool> propNames = null; foreach (KeyValuePair<Type, Dictionary<string, bool>> info in s_propertyHints) if (t == info.Key || t.IsSubclassOf(info.Key)) { propNames = info.Value; break; } foreach (PropertyInfo p in props) { bool sideEffect; if (propNames != null && propNames.TryGetValue(p.Name, out sideEffect)) { if (!sideEffect) dumpProperty(p, o, depth + 1, true); else { process2(p.Name, p.PropertyType, "<ignored>", depth + 1); _out.AppendLine(); } } else dumpProperty(p, o, depth + 1, false); } foreach (FieldInfo f in fi) dumpField(f, o, depth + 1); } _out.Append(new string(' ', depth * 2)); _out.Append("}"); } private static string toEscapedString(object o) { return o.ToString().Replace("\r", "\\r").Replace("\n", "\\n").Replace("\b", "\\b").Replace("\t", "\\t"); } private void writeBrace(object o) { _out.AppendFormat("{{ /* #{0}, {1:x8} */ ", _counter, o.GetHashCode()); _out.AppendLine(); } private void dumpProperty(PropertyInfo p, object o, int level, bool asString) { try { if (p.GetIndexParameters().Length == 0) { object obj = p.GetValue(o, null); if (asString) process2(p.Name, (obj == null) ? p.PropertyType : obj.GetType(), (obj ?? "<null>").ToString(), level); else process2(p.Name, (obj == null) ? p.PropertyType : obj.GetType(), obj, level); _out.AppendLine(); } else { _out.Append(new string(' ', level * 2)); _out.AppendLine(p.Name + " = " + "(" + GetFriendlyTypeName(p.PropertyType) + ") ??? indexed property ignored"); } } catch (Exception e) { _out.Append(new string(' ', level * 2)); _out.AppendLine(p.Name + " = " + "??? thrown " + e.GetType().FullName); } } private void dumpField(FieldInfo p, object o, int level) { try { object obj = p.GetValue(o); process2(p.Name, (obj == null) ? p.FieldType : obj.GetType(), obj, level); _out.AppendLine(); } catch (Exception e) { _out.Append(new string(' ', level * 2)); _out.AppendLine(p.Name + " = " + "??? thrown " + e.GetType().FullName); } } private void processEnumerables(IEnumerable enumerable, int nLevel) { int index = 0; foreach (object info in enumerable) { Type tinside = info == null ? typeof(object) : info.GetType(); process2("[" + index + "]", tinside, info, nLevel + 1); _out.AppendLine(); if (index++ > _settings.MaxItems) { _out.AppendLine("..."); break; } } } private void processArray(Type t, Array arr, int nLevel) { Type tInside = t.GetElementType(); if (tInside == typeof(byte)) { byte[] b = (byte[])arr; _out.AppendFormat(" {0} bytes [ ", arr.Length); for (int i = 0; i < b.Length; ++i) { if (i != 0) _out.Append(' '); _out.Append(b[i].ToString("x2")); if (i > _settings.MaxItems) { _out.Append("..."); break; } } _out.Append(" ]"); return; } _out.Append(" array[" + arr.Length + "] "); writeBrace(arr); processEnumerables(arr, nLevel); } #endregion }}Lines 501–726 of 726. Previous lines
// FileSystemInfo Parent and Root properties are examples of "bloat" properties and should be dumped with ToString Dictionary<string, bool> data = new Dictionary<string, bool>(); data["Parent"] = false; data["Root"] = false; s[typeof(FileSystemInfo)] = data; return s; } private readonly StringBuilder _out = new StringBuilder(10000); readonly Dictionary<object, int> _usedMap = new Dictionary<object, int>(new ReferenceComparer()); private int _counter = 0; void process2(string name, Type t, object o, int depth) { string typeName = GetFriendlyTypeName(t, _settings.UseFullClassNames); _out.Append(new string(' ', depth * 2)); if (!string.IsNullOrEmpty(name)) _out.Append(name + " = "); _out.Append("(" + typeName + ") "); if (o == null) { _out.Append("<null>"); return; } if ((t != typeof(string) && (o is string)) || _settings.MaxDepth <= depth) { _out.Append("\"" + toEscapedString(o) + "\" /* ToString */"); return; } if (t == typeof(string) || (o is string)) { _out.Append("\"" + toEscapedString(o) + "\""); return; } BindingFlags flags = BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public; if (_settings.DisplayPrivate) flags |= BindingFlags.NonPublic; PropertyInfo[] props = t.GetProperties(flags | BindingFlags.GetProperty); FieldInfo[] fi = t.GetFields(flags); if (t.IsPrimitive || t.IsEnum || (t.IsValueType && props.Length == 0 && fi.Length == 0) || s_bloatTypes.ContainsKey(t.FullName) || t == typeof(decimal)) { if ((t == typeof(int)) || (t == typeof(byte)) || (t == typeof(uint)) || t == typeof(long) || t == typeof(ulong)) _out.AppendFormat(" {0} (0x{0:x})", o); else if (t == typeof(DateTime) || t == typeof(DateTime?)) _out.AppendFormat("{0:o} ({1})", o, ((DateTime)o).Kind); else if (t == typeof(Guid)) _out.Append(((Guid)o).ToString("B")); else if (t == typeof(bool)) _out.Append(((bool)o) ? "true" : "false"); else if (t.IsEnum) _out.AppendFormat("[{0}] /* 0x{0:x} */", o); else _out.AppendFormat("[{0}]", toEscapedString(o)); return; } if (t.IsClass) { int id; if (_usedMap.TryGetValue(o, out id)) { _out.AppendFormat("<see #{0}, {1:x8} above>", id, o.GetHashCode()); return; } _usedMap[o] = ++_counter; } if (t.IsArray && ((Array)o).Rank == 1) { Array arr; if (t.IsArray) arr = (o as Array); else arr = t.GetMethod("ToArray").Invoke(o, new object[] { }) as Array; processArray(t, arr, depth); } else if (o as IEnumerable != null) { writeBrace(o); processEnumerables(o as IEnumerable, depth); } else { writeBrace(o); Dictionary<string, bool> propNames = null; foreach (KeyValuePair<Type, Dictionary<string, bool>> info in s_propertyHints) if (t == info.Key || t.IsSubclassOf(info.Key)) { propNames = info.Value; break; } foreach (PropertyInfo p in props) { bool sideEffect; if (propNames != null && propNames.TryGetValue(p.Name, out sideEffect)) { if (!sideEffect) dumpProperty(p, o, depth + 1, true); else { process2(p.Name, p.PropertyType, "<ignored>", depth + 1); _out.AppendLine(); } } else dumpProperty(p, o, depth + 1, false); } foreach (FieldInfo f in fi) dumpField(f, o, depth + 1); } _out.Append(new string(' ', depth * 2)); _out.Append("}"); } private static string toEscapedString(object o) { return o.ToString().Replace("\r", "\\r").Replace("\n", "\\n").Replace("\b", "\\b").Replace("\t", "\\t"); } private void writeBrace(object o) { _out.AppendFormat("{{ /* #{0}, {1:x8} */ ", _counter, o.GetHashCode()); _out.AppendLine(); } private void dumpProperty(PropertyInfo p, object o, int level, bool asString) { try { if (p.GetIndexParameters().Length == 0) { object obj = p.GetValue(o, null); if (asString) process2(p.Name, (obj == null) ? p.PropertyType : obj.GetType(), (obj ?? "<null>").ToString(), level); else process2(p.Name, (obj == null) ? p.PropertyType : obj.GetType(), obj, level); _out.AppendLine(); } else { _out.Append(new string(' ', level * 2)); _out.AppendLine(p.Name + " = " + "(" + GetFriendlyTypeName(p.PropertyType) + ") ??? indexed property ignored"); } } catch (Exception e) { _out.Append(new string(' ', level * 2)); _out.AppendLine(p.Name + " = " + "??? thrown " + e.GetType().FullName); } } private void dumpField(FieldInfo p, object o, int level) { try { object obj = p.GetValue(o); process2(p.Name, (obj == null) ? p.FieldType : obj.GetType(), obj, level); _out.AppendLine(); } catch (Exception e) { _out.Append(new string(' ', level * 2)); _out.AppendLine(p.Name + " = " + "??? thrown " + e.GetType().FullName); } } private void processEnumerables(IEnumerable enumerable, int nLevel) { int index = 0; foreach (object info in enumerable) { Type tinside = info == null ? typeof(object) : info.GetType(); process2("[" + index + "]", tinside, info, nLevel + 1); _out.AppendLine(); if (index++ > _settings.MaxItems) { _out.AppendLine("..."); break; } } } private void processArray(Type t, Array arr, int nLevel) { Type tInside = t.GetElementType(); if (tInside == typeof(byte)) { byte[] b = (byte[])arr; _out.AppendFormat(" {0} bytes [ ", arr.Length); for (int i = 0; i < b.Length; ++i) { if (i != 0) _out.Append(' '); _out.Append(b[i].ToString("x2")); if (i > _settings.MaxItems) { _out.Append("..."); break; } } _out.Append(" ]"); return; } _out.Append(" array[" + arr.Length + "] "); writeBrace(arr); processEnumerables(arr, nLevel); } #endregion } }