// Tries to lazily add the immediate children for a given node. // called on UI thread. static public void TryExpandNode(MainForm parent, TreeNode node) { MDbgValue val = (MDbgValue)node.Tag; if (val == null) { return; } node.Tag = null; // only expand it once. Else we'll keep readding the children on each select. MDbgValue[] items = null; parent.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); Debug.Assert(val.Process == proc); if (val.IsArrayType) { items = val.GetArrayItems(); } else if (val.IsComplexType) { items = val.GetFields().Concat( val.GetProperties()).ToArray(); } }); // Nothing to expand. if (items == null) { return; } // This node had a dummy sub-node so that it's marked as expandable. When we get the // BeforeExpand event, then we kill the dummy node and replace with real nodes. // We use a dummy node instead of real nodes because it lets us avoid having to add all the real nodes // (which may be a lot of work). node.Nodes.Clear(); // delete dummy node. foreach (MDbgValue field in items) { PrintInternal(parent, field, node.Nodes); } }
string SerializeValue(MDbgValue value, bool itemsOnly, int itemsMaxCount) { string result = ""; MDbgValue[] items = null; MDbgValue[] diaplayItems = null; //decorated (fake) display items int tempMaxCount = itemsMaxCount; tempMaxCount++; if (value.IsArrayType) { items = value.GetArrayItems(tempMaxCount); } else if (value.IsListType) { diaplayItems = value.GenerateListItems(tempMaxCount); } else if (value.IsDictionaryType) { diaplayItems = value.GenerateDictionaryItems(tempMaxCount); } if (!itemsOnly && value.IsComplexType) { if (!IsPrimitiveType(value)) //boxed primitive type have their MDbgValue set to ComplexType { items = value.GetFields().ToArray(); try { items = items.Concat(value.GetProperties()).ToArray(); } catch { } } } if (items != null || itemsOnly) { string logicalItems = ""; if (diaplayItems != null) { MDbgValue truncatedValue = null; if (diaplayItems.Count() > itemsMaxCount) { truncatedValue = diaplayItems.Last(); } logicalItems = diaplayItems.Select(x => { x.IsFake = true; if (truncatedValue != null && x == truncatedValue) { return(Serialize(x, "...", "...")); } else { return(Serialize(x)); } }).Join(); } string rawItems = ""; if (items != null) { bool hasIndexer = value.IsListType || value.IsDictionaryType; MDbgValue truncatedValue = null; if (items.Count() > itemsMaxCount) { truncatedValue = items.Last(); } rawItems = items.Where(x => !x.Name.Contains("$")) //ignore any internal vars .Where(x => !hasIndexer || x.Name != "Item") .Select(x => { if (truncatedValue != null && x == truncatedValue) { return(Serialize(x, "...", "...")); } else { return(Serialize(x)); } }) .Join(); } result = "<items>" + logicalItems + rawItems + "</items>"; } return(result); }