private static bool FilterElement(StringBuilder sb, object obj, object key, object val, bool pretty, bool includeType, bool showNulls, bool isArray, int depth, List <object> recursionStack, KeyValuePairToStringFilter filter = null) { bool unfiltered = true; if (filter != null) { string result = filter.Invoke(obj, key, val); unfiltered = result == null; if (!unfiltered && result.Length != 0) { sb.Append(result); return(true); } } if (unfiltered) { if (!isArray) { sb.Append(key).Append(pretty ? " : " : ":"); } sb.Append(Stringify(val, pretty, includeType, showNulls, true, depth + 1, recursionStack)); return(true); } return(false); }
/// <summary> /// stringifies an object using custom NonStandard rules /// </summary> /// <param name="obj"></param> /// <param name="pretty"></param> /// <param name="showType">include "=TypeName" if there could be ambiguity because of inheritance</param> /// <param name="depth"></param> /// <param name="rStack">used to prevent recursion stack overflows</param> /// <param name="filter">object0 is the object, object1 is the member, object2 is the value. if it returns null, print as usual. if returns "", skip print.</param> /// <param name="howToMarkStrongType">if null, use <see cref="StringifyTypeOfDictionary"/>, which is expected by <see cref="NonStandard.Data.CodeConvert.TryParse"/></param> /// <returns></returns> public static string Stringify(this object obj, bool pretty = true, bool showType = true, bool showNulls = false, bool showBoundary = true, int depth = 0, List <object> rStack = null, KeyValuePairToStringFilter filter = null, Func <Type, string> howToMarkStrongType = null) { if (obj == null) { return(showNulls ? "null" : ""); } if (filter != null) { string res = filter.Invoke(obj, null, null); if (res != null) { return(res); } } Type t = obj.GetType(); MethodInfo stringifyMethod = t.GetMethod("Stringify", Type.EmptyTypes); if (stringifyMethod != null) { return(stringifyMethod.Invoke(obj, Array.Empty <object>()) as string); } StringBuilder sb = new StringBuilder(); bool showTypeHere = showType; // no need to print type if there isn't type ambiguity if (showType) { Type b = t.BaseType; // if the parent class is a base class, there isn't any ambiguity if (b == typeof(ValueType) || b == typeof(System.Object) || b == typeof(Array) || t.GetCustomAttributes(false).FindIndex(o => o.GetType() == typeof(StringifyHideTypeAttribute)) >= 0) { showTypeHere = false; } } if (obj is string || t.IsPrimitive || t.IsEnum) { return(StringifiedSimple(sb, obj, showBoundary).ToString()); } if (rStack == null) { rStack = new List <object>(); } int recursionIndex = rStack.IndexOf(obj); if (recursionIndex >= 0) { return(sb.Append("/* recursed " + (rStack.Count - recursionIndex) + " */").ToString()); } rStack.Add(obj); Type listT = t.GetIListType(); if (t.IsArray || listT != null) { StringifiedList(sb, obj, listT, depth, howToMarkStrongType, filter, rStack, pretty, showBoundary, showType, showTypeHere, showNulls); } else { StringifiedObject(sb, t, obj, depth, howToMarkStrongType, filter, rStack, pretty, showBoundary, showType, showTypeHere, showNulls); } if (sb.Length == 0) { sb.Append(obj.ToString()); } return(sb.ToString()); }