diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj index 01254d91f4..096f33192b 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj @@ -255,8 +255,10 @@ Code + + diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs index 0cf271b494..c96c5d35dc 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs @@ -105,7 +105,7 @@ namespace Debugger.AddIn.TreeModel int count = 0; GetValueException error = null; try { - count = GetIListCount(targetObject); + count = targetObject.GetIListCount(); } catch (GetValueException e) { // Cannot yield a value in the body of a catch clause (CS1631) error = e; diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Utils.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Utils.cs index 8cbf563bdb..3b684212fa 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Utils.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Utils.cs @@ -35,33 +35,6 @@ namespace Debugger.AddIn.TreeModel Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => frame.Continue = false)); Dispatcher.PushFrame(frame); } - - /// - /// Evaluates System.Collections.ICollection.Count property on given object. - /// - /// Evaluating System.Collections.ICollection.Count on targetObject failed. - public static int GetIListCount(Expression targetObject) - { - Value list = targetObject.Evaluate(WindowsDebugger.CurrentProcess); - var iCollectionInterface = list.Type.GetInterface(typeof(ICollection).FullName); - if (iCollectionInterface == null) - throw new GetValueException(targetObject, targetObject.PrettyPrint() + " does not implement System.Collections.ICollection"); - PropertyInfo countProperty = iCollectionInterface.GetProperty("Count"); - // Do not get string representation since it can be printed in hex - return (int)list.GetPropertyValue(countProperty).PrimitiveValue; - } - - /// - /// Prepends a cast to IList before the given Expression. - /// - public static Expression CastToIList(this Expression expr) - { - return new CastExpression( - new TypeReference(typeof(IList).FullName), - expr.Parenthesize(), - CastType.Cast - ); - } } public class AbortedBecauseDebuggeeResumedException: System.Exception diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RouteVertex.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RouteVertex.cs index b6dd3e2992..f729be16ab 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RouteVertex.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RouteVertex.cs @@ -45,6 +45,8 @@ namespace Debugger.AddIn.Visualizers.Graph.SplineRouting public bool IsUsed { get; set; } public bool IsAvailable { get { return !IsUsed && !IsEdgeEndpoint; } } + public double Penalization { get; set; } + public void Reset() { Distance = 10e+6; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RoutedEdge.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RoutedEdge.cs index 9618bf6926..08f9075129 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RoutedEdge.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/RouteGraph/RoutedEdge.cs @@ -40,10 +40,8 @@ namespace Debugger.AddIn.Visualizers.Graph.SplineRouting { get { - if (this.splinePoints == null) - { - List sPoints = RouteSpline(this.Points); - splinePoints = sPoints.AsReadOnly(); + if (this.splinePoints == null) { + this.splinePoints = RouteSpline(this.Points).AsReadOnly(); } return this.splinePoints; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/ShortestPath/DijkstraShortestPathFinder.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/ShortestPath/DijkstraShortestPathFinder.cs index a793b57d27..26df3bec61 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/ShortestPath/DijkstraShortestPathFinder.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/SplineRouting/ShortestPath/DijkstraShortestPathFinder.cs @@ -41,8 +41,9 @@ namespace Debugger.AddIn.Visualizers.Graph.SplineRouting reached = true; } foreach (var edge in minVertex.Neighbors) { - if (minVertex.Distance + edge.Length < edge.EndVertex.Distance) { - edge.EndVertex.Distance = minVertex.Distance + edge.Length; + double newDist = minVertex.Distance + edge.Length + edge.EndVertex.Penalization; + if (newDist < edge.EndVertex.Distance) { + edge.EndVertex.Distance = newDist; edge.EndVertex.Predecessor = minVertex; } } @@ -53,7 +54,7 @@ namespace Debugger.AddIn.Visualizers.Graph.SplineRouting if (pathVertex == null) break; path.Add(pathVertex); - //pathVertex.IsUsed = true; + //pathVertex.Penalization += 16; // penalize path vertices so that next path tend to choose different vertices pathVertex = pathVertex.Predecessor; } path.Add(start); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentNode.cs index 517c94b663..6c0ddc7659 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentNode.cs @@ -174,23 +174,23 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout } } - private string GetContentNodeName(AbstractNode source) + string GetContentNodeName(AbstractNode source) { if (source is ThisNode) { return "this"; } - if (source is NonPublicMembersNode) { return StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicMembers}"); } - + if (source is RawViewNode) { + return StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.RawView}"); + } var sourceBaseClassNode = source as BaseClassNode; if (sourceBaseClassNode != null) { string baseClassString = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}"); return string.Format("{0} ({1})", sourceBaseClassNode.TypeName, baseClassString); } - - throw new ApplicationException("Unknown AbstractNode."); + throw new ApplicationException("Unknown AbstractNode: " + source.GetType()); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs index 81181b0f89..97e8d498c5 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.Reflection; - using Debugger.AddIn.TreeModel; using Debugger.AddIn.Visualizers.Common; +using Debugger.AddIn.Visualizers.Graph.Layout; using Debugger.AddIn.Visualizers.Utils; using Debugger.MetaData; using ICSharpCode.NRefactory; @@ -60,7 +60,7 @@ namespace Debugger.AddIn.Visualizers.Graph /// /// Binding flags for getting member expressions. /// - private readonly BindingFlags memberBindingFlags = + private readonly BindingFlags publicInstanceMemberFlags = BindingFlags.Public | BindingFlags.Instance; private readonly BindingFlags nonPublicInstanceMemberFlags = @@ -145,61 +145,56 @@ namespace Debugger.AddIn.Visualizers.Graph /// private void loadContent(ObjectGraphNode thisNode) { - thisNode.Content = new ThisNode(); - ThisNode contentRoot = thisNode.Content; + var contentRoot = new ThisNode(); + thisNode.Content = contentRoot; DebugType collectionType; DebugType itemType; if (thisNode.PermanentReference.Type.ResolveIListImplementation(out collectionType, out itemType)) { + //AddRawViewNode(contentRoot, thisNode); // it is an IList - loadNodeCollectionContent(contentRoot, thisNode.Expression, collectionType); + LoadNodeCollectionContent(contentRoot, thisNode.Expression, collectionType); } else if (thisNode.PermanentReference.Type.ResolveIEnumerableImplementation(out collectionType, out itemType)) { + //AddRawViewNode(contentRoot, thisNode); // it is an IEnumerable DebugType debugListType; var debugListExpression = DebuggerHelpers.CreateDebugListExpression(thisNode.Expression, itemType, out debugListType); - loadNodeCollectionContent(contentRoot, debugListExpression, debugListType); + LoadNodeCollectionContent(contentRoot, debugListExpression, debugListType); } else { // it is an object - loadNodeObjectContent(contentRoot, thisNode.Expression, thisNode.PermanentReference.Type); + LoadNodeObjectContent(contentRoot, thisNode.Expression, thisNode.PermanentReference.Type); } } + + void AddRawViewNode(AbstractNode contentRoot, ObjectGraphNode thisNode) + { + var rawViewNode = new RawViewNode(); + contentRoot.AddChild(rawViewNode); + LoadNodeObjectContent(rawViewNode, thisNode.Expression, thisNode.PermanentReference.Type); + } - private void loadNodeCollectionContent(AbstractNode node, Expression thisObject, DebugType iListType) + void LoadNodeCollectionContent(AbstractNode node, Expression thisObject, DebugType iListType) { thisObject = thisObject.CastToIList(); - int listCount = getIListCount(thisObject, iListType); + int listCount = thisObject.GetIListCount(); - for (int i = 0; i < listCount; i++) - { + for (int i = 0; i < listCount; i++) { Expression itemExpr = thisObject.AppendIndexer(i); - PropertyNode itemNode = new PropertyNode( new ObjectGraphProperty { Name = "[" + i + "]", Expression = itemExpr, Value = "", IsAtomic = true, TargetNode = null }); node.AddChild(itemNode); } } - private int getIListCount(Expression targetObject, DebugType iListType) - { - PropertyInfo countProperty = iListType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count"); - try { - // Do not get string representation since it can be printed in hex later - Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty); - return (int)countValue.PrimitiveValue; - } catch (GetValueException) { - return -1; - } - } - - private void loadNodeObjectContent(AbstractNode node, Expression expression, DebugType type) + void LoadNodeObjectContent(AbstractNode node, Expression expression, DebugType type) { // base if (type.BaseType != null && type.BaseType.FullName != "System.Object") { var baseClassNode = new BaseClassNode(type.BaseType.FullName, type.BaseType.Name); node.AddChild(baseClassNode); - loadNodeObjectContent(baseClassNode, expression, (DebugType)type.BaseType); + LoadNodeObjectContent(baseClassNode, expression, (DebugType)type.BaseType); } // non-public members @@ -215,17 +210,12 @@ namespace Debugger.AddIn.Visualizers.Graph } // public members - foreach (var property in getPublicProperties(expression, type)) + foreach (var property in getProperties(expression, type, this.publicInstanceMemberFlags)) { node.AddChild(new PropertyNode(property)); } } - private List getPublicProperties(Expression expression, DebugType shownType) - { - return getProperties(expression, shownType, this.memberBindingFlags); - } - private List getProperties(Expression expression, DebugType shownType, BindingFlags flags) { List propertyList = new List(); @@ -261,8 +251,8 @@ namespace Debugger.AddIn.Visualizers.Graph /// private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedExpressions expandedNodes) { - //foreach(ObjectGraphProperty complexProperty in thisNode.ComplexProperties) - foreach(ObjectGraphProperty complexProperty in thisNode.Properties) + // evaluate properties first in case property getters are changing some fields - the fields will then have correct values + foreach(ObjectGraphProperty complexProperty in thisNode.PropertiesFirstThenFields) { ObjectGraphNode targetNode = null; // We are only evaluating expanded nodes here. diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs index d2dc8c064c..87502b469d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs @@ -39,9 +39,20 @@ namespace Debugger.AddIn.Visualizers.Graph /// public string TypeName { get; set; } + /// + /// All ObjectGraphProperties in the property tree of this node. + /// public IEnumerable Properties { get { return this.Content.FlattenPropertyNodes().Select(node => {return node.Property; }); } } + + /// + /// Same as but sorted so that .NET properties come first, and .NET fields after them. + /// + public IEnumerable PropertiesFirstThenFields + { + get { return this.Properties.OrderBy(prop => prop.MemberInfo, PropertiesFirstComparer.Instance); } + } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs index 899d258e73..c9b642c0e7 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Text; - using Debugger.AddIn.Visualizers.Utils; +using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Services; using ICSharpCode.NRefactory.Ast; @@ -37,7 +37,6 @@ namespace Debugger.AddIn.Visualizers.Graph public void Evaluate() { if (this.Expression == null) throw new DebuggerVisualizerException("Cannot evaluate property with missing Expression"); - Value debuggerVal; try { debuggerVal = this.Expression.Evaluate(WindowsDebugger.CurrentProcess); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/PropertiesFirstComparer.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/PropertiesFirstComparer.cs new file mode 100644 index 0000000000..35f59f0d82 --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/PropertiesFirstComparer.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System; +using System.Reflection; + +namespace Debugger.AddIn.Visualizers.Graph +{ + /// + /// Compares members - .NET properties come before .NET fields. + /// + public sealed class PropertiesFirstComparer : IComparer + { + private static PropertiesFirstComparer instance = new PropertiesFirstComparer(); + + public static PropertiesFirstComparer Instance { + get { + return instance; + } + } + + private PropertiesFirstComparer() + { + } + + public int Compare(MemberInfo x, MemberInfo y) + { + if ((x is PropertyInfo) && (y is FieldInfo)) return -1; + if ((y is PropertyInfo) && (x is FieldInfo)) return 1; + return x.Name.CompareTo(y.Name); + } + } +} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/NonPublicMembersNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/NonPublicMembersNode.cs index 69bba74baf..e77be9e17f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/NonPublicMembersNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/NonPublicMembersNode.cs @@ -1,14 +1,12 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) -using System.Collections.Generic; -using System.Linq; using System; namespace Debugger.AddIn.Visualizers.Graph { /// - /// Description of NonPublicMembersNode. + /// Contains "Non-public members" of a node in the ObjectGraph. /// public class NonPublicMembersNode : AbstractNode { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/PropertyNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/PropertyNode.cs index eaf4fbf937..eb82067005 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/PropertyNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/PropertyNode.cs @@ -7,7 +7,7 @@ using System; namespace Debugger.AddIn.Visualizers.Graph { /// - /// Node containing ObjectGraphProperty. + /// Contains ObjectGraphProperty. /// public class PropertyNode : AbstractNode { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/RawViewNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/RawViewNode.cs new file mode 100644 index 0000000000..0646d27f49 --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/TreeModel/RawViewNode.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) + +using System; + +namespace Debugger.AddIn.Visualizers.Graph +{ + /// + /// Contains "Raw view" of collection properties in ObjectGraph. + /// + public class RawViewNode : AbstractNode + { + public RawViewNode() + { + } + } +} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs index 22aed132d9..aae276e513 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs @@ -2,13 +2,15 @@ // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Debugger.AddIn.Visualizers.Common; using Debugger.AddIn.Visualizers.Utils; using Debugger.MetaData; using ICSharpCode.Core; using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop.Services; -using System.Reflection; namespace Debugger.AddIn.Visualizers.GridVisualizer { @@ -32,7 +34,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer public int GetCount() { if (this.listCount == null) { - this.listCount = Debugger.AddIn.TreeModel.Utils.GetIListCount(this.targetObject); + this.listCount = this.targetObject.GetIListCount(); } return this.listCount.Value; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IListNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IListNode.cs index fa9dee2785..7a1b1b26ad 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IListNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IListNode.cs @@ -1,6 +1,7 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) +using Debugger.AddIn.Visualizers.Utils; using ICSharpCode.NRefactory.Ast; using System.Collections; using System.Collections.Generic; @@ -12,20 +13,20 @@ namespace Debugger.AddIn.TreeModel { public class IListNode : TreeNode { - Expression targetObject; - int count; + Expression targetList; + int listCount; - public IListNode(Expression targetObject) + public IListNode(Expression targetListObject) { - this.targetObject = targetObject; + this.targetList = targetListObject; this.Name = "IList"; - this.count = Utils.GetIListCount(this.targetObject); - this.ChildNodes = Utils.LazyGetItemsOfIList(this.targetObject); + this.listCount = this.targetList.GetIListCount(); + this.ChildNodes = Utils.LazyGetItemsOfIList(this.targetList); } public override bool HasChildNodes { - get { return this.count > 0; } + get { return this.listCount > 0; } } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs index cea98134eb..c962d91625 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs @@ -110,5 +110,31 @@ namespace Debugger.AddIn.Visualizers.Utils { return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(); } + + /// + /// Evaluates System.Collections.ICollection.Count property on given object. + /// + /// Evaluating System.Collections.ICollection.Count on targetObject failed. + public static int GetIListCount(this Expression targetObject) + { + Value list = targetObject.Evaluate(WindowsDebugger.CurrentProcess); + var iCollectionType = list.Type.GetInterface(typeof(System.Collections.ICollection).FullName); + if (iCollectionType == null) + throw new GetValueException(targetObject, targetObject.PrettyPrint() + " does not implement System.Collections.ICollection"); + // Do not get string representation since it can be printed in hex + return (int)list.GetPropertyValue(iCollectionType.GetProperty("Count")).PrimitiveValue; + } + + /// + /// Prepends a cast to IList before the given Expression. + /// + public static Expression CastToIList(this Expression expr) + { + return new CastExpression( + new TypeReference(typeof(System.Collections.IList).FullName), + expr.Parenthesize(), + CastType.Cast + ); + } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/TypeResolver.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/TypeResolver.cs index 88b5b87431..ff9d92e854 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/TypeResolver.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/TypeResolver.cs @@ -12,7 +12,7 @@ namespace Debugger.AddIn.Visualizers.Utils /// /// Helper for obtaining information about DebugType. /// - public static class TypeResolverExtension + public static class TypeResolver { /// /// Gets generic interface this type implements.