/// <returns>An <see cref="ObjectElement"/> of type 'Root'</returns> internal ObjectElement ExploreException(Exception exception) { System.Diagnostics.Debug.Assert(VisitedObjects == null, "VisitedObjects should be reset at the exit of this method"); try { // Create root VisitedObjects = new Dictionary <object, ObjectElement>(); var root = ObjectElement.CreateRoot(); // Create element for each InnerException for (var current = exception; current != null; current = current.InnerException) { var element = Explore("", typeof(Exception).ToString(), current, 0); root.Children.Insert(0, element); } return(root); } finally { if (VisitedObjects != null) { VisitedObjects = null; } } }
/// <returns>The last exception's message</returns> public string GetMessage() { System.Diagnostics.Debug.Assert(Tree != null, "The 'Tree' property sould have been initialized in the constructor"); if ((Tree == null) || (Tree.Children.Count <= 0)) { return(""); } // Get the last exception ObjectElement lastException = null; foreach (var child in Tree.Children) { if (child.Type == ObjectElement.Types.Exception) { lastException = child; } } if (lastException == null) { System.Diagnostics.Debug.Fail("No exception in Tree"); return(""); } var translatable = lastException.Value as TranslatableElement; if (translatable != null) { return(translatable.ToString(this)); } else { return(lastException.Value.ToString()); } }
public Manager(ObjectElement tree) { Translate = Translate_DefaultImplementation; System.Diagnostics.Debug.Assert(tree != null, "The provided parameter 'tree' is null"); System.Diagnostics.Debug.Assert(tree.Type == ObjectElement.Types.Root, "The provided tree is supposed to be a 'Root' element"); Tree = tree; }
internal static ObjectElement CloneElement(string name, string className, ObjectElement src) { return(new ObjectElement { Type = src.Type, Children = src.Children, Value = src.Value, Name = name, ClassName = string.IsNullOrEmpty(src.ClassName) ? className : src.ClassName }); }
public static SerializableNode[] CreateSerializableNodes(ObjectElement tree) { var helper = new SerializerHelper(); // Get the list of objects contained in the Tree helper.Explore( tree ); // Create the list of nodes var objects = new SerializableNode[ helper.VisitedObjects.Count ]; int i=0; foreach( var obj in helper.VisitedObjects.Values ) objects[i++] = obj; return objects; }
public static SerializableNode[] CreateSerializableNodes(ObjectElement tree) { var helper = new SerializerHelper(); // Get the list of objects contained in the Tree helper.Explore(tree); // Create the list of nodes var objects = new SerializableNode[helper.VisitedObjects.Count]; int i = 0; foreach (var obj in helper.VisitedObjects.Values) { objects[i++] = obj; } return(objects); }
/// <remarks>Recursive</remarks> private void Explore(ObjectElement node) { System.Diagnostics.Debug.Assert(VisitedObjects != null, "Property 'VisitedElements' is not set"); System.Diagnostics.Debug.Assert(node != null, "Parameter 'node' is not set"); System.Diagnostics.Debug.Assert(node.Children != null, "Node's children is not set"); int id = node.GetHashCode(); if (VisitedObjects.ContainsKey(id)) { return; } int[] children = null; if (node.Children.Count > 0) { children = new int[node.Children.Count]; for (int i = 0; i < node.Children.Count; ++i) { children[i] = node.Children[i].GetHashCode(); } } var name_translatable = node.Name as TranslatableElement; var value_translatable = node.Value as TranslatableElement; var xmlNode = new SerializableNode { ID = id, Type = node.Type, NameTranslatable = name_translatable != null ? new SerializableTranslatable(name_translatable) : null, NameString = name_translatable == null ? (string)node.Name : null, Class = node.ClassName, ValueTranslatable = value_translatable != null ? new SerializableTranslatable(value_translatable) : null, ValuePrimitive = value_translatable == null ? new SerializablePrimitive(node.Value) : null, StackTrace = node.StackTrace, Children = children }; VisitedObjects.Add(node.GetHashCode(), xmlNode); foreach (var childNode in node.Children) { Explore(childNode); } }
/// <remarks>Recursive</remarks> private void Write(ObjectElement node, string indentation, int currentDepth) { switch (node.Type) { case ObjectElement.Types.Exception: Writer.WriteLine(string.Format("{0}{1} ({2})", indentation, GetElementValue(node.Value, Manager), node.ClassName)); break; case ObjectElement.Types.Object: Writer.WriteLine(string.Format("{0}{1} ({2}):", indentation, GetElementName(node.Name, Manager), node.ClassName)); break; case ObjectElement.Types.Field: Writer.WriteLine(string.Format("{0}{1}: {2} ({3})", indentation, GetElementName(node.Name, Manager), GetElementValue(node.Value, Manager), node.ClassName)); break; default: throw new NotImplementedException("Element type '" + node.Type.ToString() + "' is not supported"); } indentation += Indentation; int childDepth = currentDepth + 1; if (childDepth < MaximumDepth) { foreach (var childNode in node.Children) { Write(childNode, indentation, childDepth); } } switch (node.Type) { case ObjectElement.Types.Exception: Writer.WriteLine(); foreach (string line in node.StackTrace) { Writer.WriteLine(line); } Writer.WriteLine(); break; } }
/// <remarks>Recursive</remarks> private void Explore(ObjectElement node) { System.Diagnostics.Debug.Assert( VisitedObjects != null, "Property 'VisitedElements' is not set" ); System.Diagnostics.Debug.Assert( node != null, "Parameter 'node' is not set" ); System.Diagnostics.Debug.Assert( node.Children != null, "Node's children is not set" ); int id = node.GetHashCode(); if( VisitedObjects.ContainsKey(id) ) return; int[] children = null; if( node.Children.Count > 0 ) { children = new int[ node.Children.Count ]; for( int i=0; i<node.Children.Count; ++i ) children[i] = node.Children[i].GetHashCode(); } var name_translatable = node.Name as TranslatableElement; var value_translatable = node.Value as TranslatableElement; var xmlNode = new SerializableNode { ID = id, Type = node.Type, NameTranslatable = name_translatable != null ? new SerializableTranslatable(name_translatable) : null, NameString = name_translatable == null ? (string)node.Name : null, Class = node.ClassName, ValueTranslatable = value_translatable != null ? new SerializableTranslatable(value_translatable) : null, ValuePrimitive = value_translatable == null ? new SerializablePrimitive(node.Value) : null, StackTrace = node.StackTrace, Children = children }; VisitedObjects.Add( node.GetHashCode(), xmlNode ); foreach( var childNode in node.Children ) Explore( childNode ); }
/// <returns>The root element of the tree</returns> public static ObjectElement RecreateObjectTree(SerializableNode[] nodes) { // Recreate all objects ObjectElement root = null; var elements = new Dictionary <int, ObjectElement>(); foreach (var obj in nodes) { ObjectElement element; switch (obj.Type) { case ObjectElement.Types.Root: element = ObjectElement.CreateRoot(); if (root != null) { throw new ApplicationException("There is more than 1 root element in the XML document."); } root = element; break; case ObjectElement.Types.Exception: { string str; if (obj.ValueTranslatable != null) { element = ObjectElement.CreateException(obj.ValueTranslatable.CreateTranslatableElement(), obj.Class, obj.StackTrace); } else if ((str = obj.ValuePrimitive.Value as string) != null) { element = ObjectElement.CreateException(str, obj.Class, obj.StackTrace); } else { System.Diagnostics.Debug.Fail("Unsupported element type '" + obj.ValuePrimitive.Value.GetType().FullName + "'"); continue; } break; } case ObjectElement.Types.Object: if (obj.NameTranslatable != null) { element = ObjectElement.CreateObject(obj.NameTranslatable.CreateTranslatableElement(), obj.Class); } else { element = ObjectElement.CreateObject(obj.NameString, obj.Class); } break; case ObjectElement.Types.Field: if (obj.NameTranslatable != null) { element = ObjectElement.CreateField(obj.NameTranslatable.CreateTranslatableElement(), obj.Class, obj.ValuePrimitive != null ? obj.ValuePrimitive.Value : obj.ValueTranslatable); } else { element = ObjectElement.CreateField(obj.NameString, obj.Class, obj.ValuePrimitive != null ? obj.ValuePrimitive.Value : obj.ValueTranslatable); } break; default: throw new NotImplementedException("The object type '" + obj.Type.ToString() + "' is not supported"); } elements.Add(obj.ID, element); } if (root == null) { throw new ApplicationException("There is no root element in the XML document."); } // Recreate parent/child links between objects foreach (var obj in nodes) { var parentElement = elements[obj.ID]; if (obj.Children != null) { foreach (var childObj in obj.Children) { parentElement.Children.Add(elements[childObj]); } } } return(root); }
/// <remarks>Recursive</remarks> private void Write(ObjectElement node, string indentation, int currentDepth) { switch( node.Type ) { case ObjectElement.Types.Exception: Writer.WriteLine( string.Format("{0}{1} ({2})", indentation, GetElementValue(node.Value, Manager), node.ClassName) ); break; case ObjectElement.Types.Object: Writer.WriteLine( string.Format("{0}{1} ({2}):", indentation, GetElementName(node.Name, Manager), node.ClassName) ); break; case ObjectElement.Types.Field: Writer.WriteLine( string.Format("{0}{1}: {2} ({3})", indentation, GetElementName(node.Name, Manager), GetElementValue(node.Value, Manager), node.ClassName) ); break; default: throw new NotImplementedException( "Element type '" + node.Type.ToString() + "' is not supported" ); } indentation += Indentation; int childDepth = currentDepth+1; if( childDepth < MaximumDepth ) { foreach( var childNode in node.Children ) { Write( childNode, indentation, childDepth ); } } switch( node.Type ) { case ObjectElement.Types.Exception: Writer.WriteLine(); foreach( string line in node.StackTrace ) Writer.WriteLine( line ); Writer.WriteLine(); break; } }
public JsonSerializer(Manager manager) { Tree = manager.Tree; }
public XmlSerializer(Manager manager) { Tree = manager.Tree; }
/// <remarks>Recursive</remarks> private void Explore(ObjectElement element, int depth) { System.Diagnostics.Debug.Assert( Writer != null, "Property 'Writer' is not set" ); if( depth <= 0 ) return; bool closeDiv; switch( element.Type ) { case ObjectElement.Types.Field: { closeDiv = false; string name = HttpUtility.HtmlEncode( CommonLibs.ExceptionManager.TextWriter.GetElementName(element.Name, Manager) ); string value = HttpUtility.HtmlEncode( CommonLibs.ExceptionManager.TextWriter.GetElementValue(element.Value, Manager) ); string className = HttpUtility.HtmlEncode( element.ClassName ); Writer.Write( "<div class='" + CssField + "'><span>" + name + "</span><span>" + value + "</span><span>" + className + "</span></div>" ); break; } case ObjectElement.Types.Exception: { closeDiv = true; string message = HttpUtility.HtmlEncode( CommonLibs.ExceptionManager.TextWriter.GetElementValue(element.Value, Manager) ); string className = HttpUtility.HtmlEncode( element.ClassName ); Writer.Write( "<div class='" + CssException + "'><div><span>" + message + "</span><span>" + className + "</span></div>" ); break; } case ObjectElement.Types.Object: { closeDiv = true; string name = HttpUtility.HtmlEncode( CommonLibs.ExceptionManager.TextWriter.GetElementName(element.Name, Manager) ); string className = HttpUtility.HtmlEncode( element.ClassName ); Writer.Write( "<div class='" + CssObject + "'><div><span>" + name + "</span><span>" + className + "</span></div>" ); break; } default: throw new NotImplementedException( "Element type '" + element.Type.ToString() + "' is not supported" ); } --depth; foreach( var child in element.Children ) Explore( child, depth ); if( element.StackTrace != null ) { Writer.Write( "<div class='" + CssStackTrace + "'>" ); foreach( string line in element.StackTrace ) Writer.Write( "<span>" + line + "</span>" ); Writer.Write( "</div>" ); } if( closeDiv ) Writer.Write( "</div>" ); }
private ObjectElement Explore(string fieldName, string fieldType, object currentObject, int currentDepth) { try { System.Diagnostics.Debug.Assert(fieldName != null); System.Diagnostics.Debug.Assert(fieldType != null); System.Diagnostics.Debug.Assert(currentDepth <= MaximumDepth); System.Diagnostics.Debug.Assert(VisitedObjects != null); if (currentObject == null) { return(ObjectElement.CreateField(fieldName, fieldType, NullValue)); } // Check that this object has not been visited yet ObjectElement visited; VisitedObjects.TryGetValue(currentObject, out visited); if (visited != null) { return(ObjectElement.CloneElement(fieldName, fieldType, visited)); } // Create the ObjectElement for this object and register it as visited ObjectElement currentElement; Type currentType = currentObject.GetType(); BaseException currentBaseException = null; Exception currentException = null; IDictionary currentDictionary = null; IEnumerable currentEnumerable = null; var fieldsToSkip = new Dictionary <string, object>(); string[] stackTrace = null; bool exploreChildren; if (IsDirectlyInterpretable(currentType)) { exploreChildren = false; currentElement = ObjectElement.CreateField(fieldName, currentType.FullName, currentObject); } else { exploreChildren = true; if ((currentBaseException = currentObject as BaseException) != null) { currentException = currentBaseException; if (currentBaseException.TranslatableMessage == null) { // Treat as regular exception currentBaseException = null; } fieldsToSkip.Add("InnerException", null); fieldsToSkip.Add("Message", null); fieldsToSkip.Add("TranslatableMessage", null); fieldsToSkip.Add("StackTrace", null); stackTrace = currentException.StackTrace.Split(new char[] { '\n' }); for (int i = 0; i < stackTrace.Length; ++i) { stackTrace[i] = stackTrace[i].Trim(); } } else if ((currentException = currentObject as Exception) != null) { fieldsToSkip.Add("InnerException", null); fieldsToSkip.Add("Message", null); fieldsToSkip.Add("StackTrace", null); stackTrace = currentException.StackTrace.Split(new char[] { '\n' }); for (int i = 0; i < stackTrace.Length; ++i) { stackTrace[i] = stackTrace[i].Trim(); } } if ((currentDictionary = currentObject as IDictionary) != null) { fieldsToSkip.Add("Keys", null); fieldsToSkip.Add("Values", null); fieldsToSkip.Add("Item", null); //exploreChildren = false; } else if ((currentEnumerable = currentObject as IEnumerable) != null) { //exploreChildren = false; } if (currentBaseException != null) { currentElement = ObjectElement.CreateException(currentBaseException.TranslatableMessage, currentBaseException.GetType().FullName, stackTrace); } else if (currentException != null) { currentElement = ObjectElement.CreateException(currentException.Message, currentException.GetType().FullName, stackTrace); } else { currentElement = ObjectElement.CreateObject(fieldName, currentObject.GetType().FullName); } } if (currentDepth >= MaximumDepth) { // Stop exploring exploreChildren = false; } VisitedObjects.Add(currentObject, currentElement); var childDepth = currentDepth + 1; if ((currentException == null) && (currentEnumerable == null) && (currentDictionary == null) && currentType.FullName.StartsWith("System.")) { // Don't explore childs of objects of type 'System.*' (except exceptions, enumerables and dictionaries) childDepth = MaximumDepth; } if (exploreChildren) { // Explore children foreach (var childMember in currentObject.GetType().GetMembers()) { if (fieldsToSkip.ContainsKey(childMember.Name)) { continue; } // Get the child type/value string childType; object childObject; switch (childMember.MemberType) { case MemberTypes.Field: { var field = (FieldInfo)childMember; childType = field.FieldType.FullName; childObject = field.GetValue(currentObject); break; } case MemberTypes.Property: { var property = (PropertyInfo)childMember; var propertyType = property.PropertyType; childType = propertyType.FullName; try { childObject = property.GetGetMethod().Invoke(currentObject, new object[] {}); } catch (System.Exception ex) { // Error calling the getter => Replace by an error string and continue string errorString = string.Format(GetterError, ex.GetType().FullName, ex.Message); var childElement2 = ObjectElement.CreateField(childMember.Name, childType, errorString); currentElement.Children.Add(childElement2); continue; } break; } default: // Nothing to explore continue; } // Recursive call var childElement = Explore(childMember.Name, childType, childObject, childDepth); currentElement.Children.Add(childElement); } if (currentDictionary != null) { // Add dictionary entries foreach (DictionaryEntry entry in currentDictionary) { string name; try { object key = entry.Key; if (key == null) { name = "<NULL>"; } else { name = key.ToString(); if (name.Length > MaxDictKeyLen) { name = name.Substring(0, MaxDictKeyLen); } name = "[" + name + "]"; } } catch (System.Exception ex) { // Error converting the Key to string => Replace by an error string and continue name = string.Format(GetterError, ex.GetType().FullName, ex.Message); } // Recursive call var childElement = Explore(name, typeof(object).ToString(), entry.Value, childDepth); currentElement.Children.Add(childElement); } } else if (currentEnumerable != null) { // Add enumerable entries int i = 0; foreach (object entry in currentEnumerable) { // Recursive call string name = string.Format("[{0}]", i++); var childElement = Explore(name, typeof(object).ToString(), entry, childDepth); currentElement.Children.Add(childElement); } } } return(currentElement); } catch (System.Exception ex) { // Error exploring => Replace by an error field System.Diagnostics.Debug.Fail("Explore error"); var element = ObjectElement.CreateField(fieldName, fieldType, string.Format(ExploreError, ex.GetType(), ex.Message)); return(element); } }
internal static ObjectElement CloneElement(string name, string className, ObjectElement src) { return new ObjectElement { Type = src.Type, Children = src.Children, Value = src.Value, Name = name, ClassName = string.IsNullOrEmpty(src.ClassName) ? className : src.ClassName }; }
/// <remarks>Recursive</remarks> private void Explore(ObjectElement element, int depth) { System.Diagnostics.Debug.Assert(Writer != null, "Property 'Writer' is not set"); if (depth <= 0) { return; } bool closeDiv; switch (element.Type) { case ObjectElement.Types.Field: { closeDiv = false; string name = HttpUtility.HtmlEncode(CommonLibs.ExceptionManager.TextWriter.GetElementName(element.Name, Manager)); string value = HttpUtility.HtmlEncode(CommonLibs.ExceptionManager.TextWriter.GetElementValue(element.Value, Manager)); string className = HttpUtility.HtmlEncode(element.ClassName); Writer.Write("<div class='" + CssField + "'><span>" + name + "</span><span>" + value + "</span><span>" + className + "</span></div>"); break; } case ObjectElement.Types.Exception: { closeDiv = true; string message = HttpUtility.HtmlEncode(CommonLibs.ExceptionManager.TextWriter.GetElementValue(element.Value, Manager)); string className = HttpUtility.HtmlEncode(element.ClassName); Writer.Write("<div class='" + CssException + "'><div><span>" + message + "</span><span>" + className + "</span></div>"); break; } case ObjectElement.Types.Object: { closeDiv = true; string name = HttpUtility.HtmlEncode(CommonLibs.ExceptionManager.TextWriter.GetElementName(element.Name, Manager)); string className = HttpUtility.HtmlEncode(element.ClassName); Writer.Write("<div class='" + CssObject + "'><div><span>" + name + "</span><span>" + className + "</span></div>"); break; } default: throw new NotImplementedException("Element type '" + element.Type.ToString() + "' is not supported"); } --depth; foreach (var child in element.Children) { Explore(child, depth); } if (element.StackTrace != null) { Writer.Write("<div class='" + CssStackTrace + "'>"); foreach (string line in element.StackTrace) { Writer.Write("<span>" + line + "</span>"); } Writer.Write("</div>"); } if (closeDiv) { Writer.Write("</div>"); } }