@ -4,9 +4,9 @@
using System ;
using System ;
using System.Collections.Generic ;
using System.Collections.Generic ;
using System.Reflection ;
using System.Reflection ;
using Debugger.AddIn.TreeModel ;
using Debugger.AddIn.TreeModel ;
using Debugger.AddIn.Visualizers.Common ;
using Debugger.AddIn.Visualizers.Common ;
using Debugger.AddIn.Visualizers.Graph.Layout ;
using Debugger.AddIn.Visualizers.Utils ;
using Debugger.AddIn.Visualizers.Utils ;
using Debugger.MetaData ;
using Debugger.MetaData ;
using ICSharpCode.NRefactory ;
using ICSharpCode.NRefactory ;
@ -60,7 +60,7 @@ namespace Debugger.AddIn.Visualizers.Graph
/// <summary>
/// <summary>
/// Binding flags for getting member expressions.
/// Binding flags for getting member expressions.
/// </summary>
/// </summary>
private readonly BindingFlags memberBinding Flags =
private readonly BindingFlags publicInstanceMember Flags =
BindingFlags . Public | BindingFlags . Instance ;
BindingFlags . Public | BindingFlags . Instance ;
private readonly BindingFlags nonPublicInstanceMemberFlags =
private readonly BindingFlags nonPublicInstanceMemberFlags =
@ -145,61 +145,56 @@ namespace Debugger.AddIn.Visualizers.Graph
/// <param name="thisNode"></param>
/// <param name="thisNode"></param>
private void loadContent ( ObjectGraphNode thisNode )
private void loadContent ( ObjectGraphNode thisNode )
{
{
thisNode . Conten t = new ThisNode ( ) ;
var contentRoo t = new ThisNode ( ) ;
ThisNode contentRoot = thisNode . Content ;
thisNode . Content = contentRoo t ;
DebugType collectionType ;
DebugType collectionType ;
DebugType itemType ;
DebugType itemType ;
if ( thisNode . PermanentReference . Type . ResolveIListImplementation ( out collectionType , out itemType ) )
if ( thisNode . PermanentReference . Type . ResolveIListImplementation ( out collectionType , out itemType ) )
{
{
//AddRawViewNode(contentRoot, thisNode);
// it is an IList
// it is an IList
l oadNodeCollectionContent( contentRoot , thisNode . Expression , collectionType ) ;
L oadNodeCollectionContent( contentRoot , thisNode . Expression , collectionType ) ;
} else if ( thisNode . PermanentReference . Type . ResolveIEnumerableImplementation ( out collectionType , out itemType ) ) {
} else if ( thisNode . PermanentReference . Type . ResolveIEnumerableImplementation ( out collectionType , out itemType ) ) {
//AddRawViewNode(contentRoot, thisNode);
// it is an IEnumerable
// it is an IEnumerable
DebugType debugListType ;
DebugType debugListType ;
var debugListExpression = DebuggerHelpers . CreateDebugListExpression ( thisNode . Expression , itemType , out debugListType ) ;
var debugListExpression = DebuggerHelpers . CreateDebugListExpression ( thisNode . Expression , itemType , out debugListType ) ;
l oadNodeCollectionContent( contentRoot , debugListExpression , debugListType ) ;
L oadNodeCollectionContent( contentRoot , debugListExpression , debugListType ) ;
} else {
} else {
// it is an object
// it is an object
l oadNodeObjectContent( contentRoot , thisNode . Expression , thisNode . PermanentReference . Type ) ;
L oadNodeObjectContent( contentRoot , thisNode . Expression , thisNode . PermanentReference . Type ) ;
}
}
}
}
private void loadNodeCollectionContent ( AbstractNode node , Expression thisObject , DebugType iListTyp e)
void AddRawViewNode ( AbstractNode contentRoot , ObjectGraphNode thisNod e)
{
{
thisObject = thisObject . CastToIList ( ) ;
var rawViewNode = new RawViewNode ( ) ;
int listCount = getIListCount ( thisObject , iListType ) ;
contentRoot . AddChild ( rawViewNode ) ;
LoadNodeObjectContent ( rawViewNode , thisNode . Expression , thisNode . PermanentReference . Type ) ;
}
for ( int i = 0 ; i < listCount ; i + + )
void LoadNodeCollectionContent ( AbstractNode node , Expression thisObject , DebugType iListType )
{
{
Expression itemExpr = thisObject . AppendIndexer ( i ) ;
thisObject = thisObject . CastToIList ( ) ;
int listCount = thisObject . GetIListCount ( ) ;
for ( int i = 0 ; i < listCount ; i + + ) {
Expression itemExpr = thisObject . AppendIndexer ( i ) ;
PropertyNode itemNode = new PropertyNode (
PropertyNode itemNode = new PropertyNode (
new ObjectGraphProperty { Name = "[" + i + "]" , Expression = itemExpr , Value = "" , IsAtomic = true , TargetNode = null } ) ;
new ObjectGraphProperty { Name = "[" + i + "]" , Expression = itemExpr , Value = "" , IsAtomic = true , TargetNode = null } ) ;
node . AddChild ( itemNode ) ;
node . AddChild ( itemNode ) ;
}
}
}
}
private int getIListCount ( Expression targetObject , DebugType iListType )
void LoadNodeObjectContent ( AbstractNode node , Expression expression , DebugType type )
{
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 )
{
{
// base
// base
if ( type . BaseType ! = null & & type . BaseType . FullName ! = "System.Object" )
if ( type . BaseType ! = null & & type . BaseType . FullName ! = "System.Object" )
{
{
var baseClassNode = new BaseClassNode ( type . BaseType . FullName , type . BaseType . Name ) ;
var baseClassNode = new BaseClassNode ( type . BaseType . FullName , type . BaseType . Name ) ;
node . AddChild ( baseClassNode ) ;
node . AddChild ( baseClassNode ) ;
l oadNodeObjectContent( baseClassNode , expression , ( DebugType ) type . BaseType ) ;
LoadNodeObjectContent ( baseClassNode , expression , ( DebugType ) type . BaseType ) ;
}
}
// non-public members
// non-public members
@ -215,17 +210,12 @@ namespace Debugger.AddIn.Visualizers.Graph
}
}
// public members
// public members
foreach ( var property in getPublicP roperties ( expression , type ) )
foreach ( var property in getProperties ( expression , type , this . publicInstanceMemberFlags ) )
{
{
node . AddChild ( new PropertyNode ( property ) ) ;
node . AddChild ( new PropertyNode ( property ) ) ;
}
}
}
}
private List < ObjectGraphProperty > getPublicProperties ( Expression expression , DebugType shownType )
{
return getProperties ( expression , shownType , this . memberBindingFlags ) ;
}
private List < ObjectGraphProperty > getProperties ( Expression expression , DebugType shownType , BindingFlags flags )
private List < ObjectGraphProperty > getProperties ( Expression expression , DebugType shownType , BindingFlags flags )
{
{
List < ObjectGraphProperty > propertyList = new List < ObjectGraphProperty > ( ) ;
List < ObjectGraphProperty > propertyList = new List < ObjectGraphProperty > ( ) ;
@ -261,8 +251,8 @@ namespace Debugger.AddIn.Visualizers.Graph
/// <param name="expandedNodes"></param>
/// <param name="expandedNodes"></param>
private void loadNeighborsRecursive ( ObjectGraphNode thisNode , ExpandedExpressions expandedNodes )
private void loadNeighborsRecursive ( ObjectGraphNode thisNode , ExpandedExpressions expandedNodes )
{
{
//foreach(ObjectGraphProperty complexProperty in thisNode.ComplexProperties)
// evaluate properties first in case property getters are changing some fields - the fields will then have correct values
foreach ( ObjectGraphProperty complexProperty in thisNode . Properties )
foreach ( ObjectGraphProperty complexProperty in thisNode . PropertiesFirstThenFields )
{
{
ObjectGraphNode targetNode = null ;
ObjectGraphNode targetNode = null ;
// We are only evaluating expanded nodes here.
// We are only evaluating expanded nodes here.