|
|
@ -21,12 +21,16 @@ namespace Debugger |
|
|
|
Process process; |
|
|
|
Process process; |
|
|
|
ICorDebugType corType; |
|
|
|
ICorDebugType corType; |
|
|
|
CorElementType corElementType; |
|
|
|
CorElementType corElementType; |
|
|
|
|
|
|
|
string fullName; |
|
|
|
|
|
|
|
|
|
|
|
// Class/ValueType specific data
|
|
|
|
// Class/ValueType specific
|
|
|
|
ICorDebugClass corClass; |
|
|
|
ICorDebugClass corClass; |
|
|
|
Module module; |
|
|
|
Module module; |
|
|
|
TypeDefProps classProps; |
|
|
|
TypeDefProps classProps; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Class/ValueType/Array/Ref/Ptr specific
|
|
|
|
|
|
|
|
List<DebugType> typeArguments = new List<DebugType>(); |
|
|
|
|
|
|
|
|
|
|
|
// Members of the type; empty lists if not applicable
|
|
|
|
// Members of the type; empty lists if not applicable
|
|
|
|
List<FieldInfo> fields = new List<FieldInfo>(); |
|
|
|
List<FieldInfo> fields = new List<FieldInfo>(); |
|
|
|
List<MethodInfo> methods = new List<MethodInfo>(); |
|
|
|
List<MethodInfo> methods = new List<MethodInfo>(); |
|
|
@ -74,23 +78,44 @@ namespace Debugger |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Returns a string describing the type </summary>
|
|
|
|
/// <summary> Returns a string describing the type including the namespace
|
|
|
|
public string Name { |
|
|
|
/// and generic arguments but excluding the assembly name. </summary>
|
|
|
|
|
|
|
|
public string FullName { |
|
|
|
get { |
|
|
|
get { |
|
|
|
// TODO: Improve
|
|
|
|
return fullName; |
|
|
|
if(IsClass || IsValueType) { |
|
|
|
|
|
|
|
return classProps.Name; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
System.Type managedType = this.ManagedType; |
|
|
|
|
|
|
|
if (managedType != null) { |
|
|
|
|
|
|
|
return managedType.ToString(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return "<unknown>"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Returns the number of dimensions of an array </summary>
|
|
|
|
|
|
|
|
/// <remarks> Throws <see cref="System.ArgumentException"/> if type is not array </remarks>
|
|
|
|
|
|
|
|
public int GetArrayRank() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (IsArray) { |
|
|
|
|
|
|
|
return (int)corType.Rank; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
throw new ArgumentException("Type is not array"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Returns true if the type has an element type.
|
|
|
|
|
|
|
|
/// (ie array, reference or pointer) </summary>
|
|
|
|
|
|
|
|
public bool HasElementType { |
|
|
|
|
|
|
|
get { |
|
|
|
|
|
|
|
return IsArray; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Returns an element type for array, reference or pointer.
|
|
|
|
|
|
|
|
/// Retuns null otherwise. (Secificaly, returns null for generic types) </summary>
|
|
|
|
|
|
|
|
public DebugType GetElementType() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (HasElementType) { |
|
|
|
|
|
|
|
return typeArguments[0]; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Gets a value indicating whether the type is an array </summary>
|
|
|
|
/// <summary> Gets a value indicating whether the type is an array </summary>
|
|
|
|
public bool IsArray { |
|
|
|
public bool IsArray { |
|
|
|
get { |
|
|
|
get { |
|
|
@ -99,6 +124,26 @@ namespace Debugger |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Gets a value indicating whether the immediate type is generic.
|
|
|
|
|
|
|
|
/// Arrays, references and pointers are never generic types. </summary>
|
|
|
|
|
|
|
|
public bool IsGenericType { |
|
|
|
|
|
|
|
get { |
|
|
|
|
|
|
|
return (IsClass || IsValueType) && |
|
|
|
|
|
|
|
typeArguments.Count > 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Returns generics arguments for a type or an emtpy
|
|
|
|
|
|
|
|
/// array for non-generic types. </summary>
|
|
|
|
|
|
|
|
public DebugType[] GetGenericArguments() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (IsGenericType) { |
|
|
|
|
|
|
|
return typeArguments.ToArray(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return new DebugType[] {}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Gets a value indicating whether the type is a class </summary>
|
|
|
|
/// <summary> Gets a value indicating whether the type is a class </summary>
|
|
|
|
public bool IsClass { |
|
|
|
public bool IsClass { |
|
|
|
get { |
|
|
|
get { |
|
|
@ -183,6 +228,14 @@ namespace Debugger |
|
|
|
|
|
|
|
|
|
|
|
LoadType(); |
|
|
|
LoadType(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.IsClass || this.IsValueType || this.IsArray) { |
|
|
|
|
|
|
|
foreach(ICorDebugType t in corType.EnumerateTypeParameters().Enumerator) { |
|
|
|
|
|
|
|
typeArguments.Add(DebugType.Create(process, t)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.fullName = GetFullName(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
@ -193,6 +246,29 @@ namespace Debugger |
|
|
|
return process.GetDebugType(corType); |
|
|
|
return process.GetDebugType(corType); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string GetFullName() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (IsArray) { |
|
|
|
|
|
|
|
return GetElementType().FullName + "[" + new String(',', GetArrayRank() - 1) + "]"; |
|
|
|
|
|
|
|
} else if (IsClass || IsValueType) { |
|
|
|
|
|
|
|
if (IsGenericType) { |
|
|
|
|
|
|
|
List<string> argNames = new List<string>(); |
|
|
|
|
|
|
|
foreach(DebugType arg in GetGenericArguments()) { |
|
|
|
|
|
|
|
argNames.Add(arg.FullName); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Remove generic parameter count at the end
|
|
|
|
|
|
|
|
string className = classProps.Name.Substring(0, classProps.Name.LastIndexOf('`')); |
|
|
|
|
|
|
|
return className + "<" + String.Join(",", argNames.ToArray()) + ">"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return classProps.Name; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (IsPrimitive) { |
|
|
|
|
|
|
|
return this.ManagedType.ToString(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
throw new DebuggerException("Unknown type"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Determines whether the current type is sublass of
|
|
|
|
/// <summary> Determines whether the current type is sublass of
|
|
|
|
/// the the given type. That is, it derives from the given type. </summary>
|
|
|
|
/// the the given type. That is, it derives from the given type. </summary>
|
|
|
|
/// <remarks> Returns false if the given type is same as the current type </remarks>
|
|
|
|
/// <remarks> Returns false if the given type is same as the current type </remarks>
|
|
|
@ -250,7 +326,7 @@ namespace Debugger |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TimeSpan totalTime = Util.HighPrecisionTimer.Now - startTime; |
|
|
|
TimeSpan totalTime = Util.HighPrecisionTimer.Now - startTime; |
|
|
|
process.TraceMessage("Loaded type " + this.Name + " (" + totalTime.TotalMilliseconds + " ms)"); |
|
|
|
process.TraceMessage("Loaded type " + this.FullName + " (" + totalTime.TotalMilliseconds + " ms)"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Return all public fields.</summary>
|
|
|
|
/// <summary> Return all public fields.</summary>
|
|
|
|