PageRenderTime 103ms CodeModel.GetById 20ms app.highlight 65ms RepoModel.GetById 1ms app.codeStats 1ms

/Debugger/Debugger.Core/MetaData/DebugType.cs

http://github.com/icsharpcode/ILSpy
C# | 1377 lines | 1046 code | 181 blank | 150 comment | 410 complexity | c90cdc691fe8b791bef102f3e349428c MD5 | raw file
   1// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
   2// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
   3
   4using System;
   5using System.Collections.Generic;
   6using System.Globalization;
   7using System.Reflection;
   8using System.Text;
   9
  10using Debugger.Interop.CorDebug;
  11using Debugger.Interop.MetaData;
  12using ICSharpCode.NRefactory.Ast;
  13using Mono.Cecil.Signatures;
  14
  15namespace Debugger.MetaData
  16{
  17	/// <summary>
  18	/// Represents a type in a debugee. That is, a class, array, value type or a primitive type.
  19	/// This class mimics the <see cref="System.Type"/> class.
  20	/// </summary>
  21	/// <remarks>
  22	/// If two types are identical, the references to DebugType will also be identical 
  23	/// Type will be loaded once per each appdomain.
  24	/// </remarks>
  25	[Debugger.Tests.IgnoreOnException]
  26	public class DebugType: System.Type, IDebugMemberInfo
  27	{
  28		public const BindingFlags BindingFlagsAll = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
  29		public const BindingFlags BindingFlagsAllDeclared = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
  30		public const BindingFlags BindingFlagsAllInScope = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
  31		
  32		Module module;
  33		ICorDebugType corType;
  34		CorElementType corElementType;
  35		Type primitiveType;
  36		TypeDefProps classProps;
  37		string ns;
  38		string name;
  39		string fullName;
  40		string fullNameWithoutGenericArguments;
  41		DebugType declaringType;
  42		DebugType elementType;
  43		List<DebugType> genericArguments = new List<DebugType>();
  44		List<DebugType> interfaces = new List<DebugType>();
  45		
  46		// Members of the type; empty if not applicable
  47		Dictionary<string, List<MemberInfo>> membersByName = new Dictionary<string, List<MemberInfo>>();
  48		Dictionary<int, MemberInfo> membersByToken = new Dictionary<int, MemberInfo>();
  49		
  50		internal ICorDebugType CorType {
  51			get { return corType; }
  52		}
  53		
  54		/// <inheritdoc/>
  55		public override Type DeclaringType {
  56			get { return declaringType; }
  57		}
  58		
  59		[Debugger.Tests.Ignore]
  60		public IEnumerable<DebugType> GetSelfAndDeclaringTypes()
  61		{
  62			DebugType type = this;
  63			while(type != null) {
  64				yield return type;
  65				type = (DebugType)type.DeclaringType;
  66			}
  67		}
  68		
  69		/// <summary> The AppDomain in which this type is loaded </summary>
  70		public AppDomain AppDomain {
  71			get { return module.AppDomain; }
  72		}
  73		
  74		/// <summary> The Process in which this type is loaded </summary>
  75		public Process Process {
  76			get { return module.Process; }
  77		}
  78		
  79		/// <summary> The Module in which this type is loaded </summary>
  80		public Debugger.Module DebugModule {
  81			get { return module; }
  82		}
  83		
  84		/// <inheritdoc/>
  85		public override int MetadataToken {
  86			get { return (int)classProps.Token; }
  87		}
  88		
  89		/// <inheritdoc/>
  90		public override System.Reflection.Module Module {
  91			get { throw new NotSupportedException(); }
  92		}
  93		
  94		/// <inheritdoc/>
  95		public override string Name {
  96			get { return name; }
  97		}
  98		
  99		/// <inheritdoc/>
 100		public override Type ReflectedType {
 101			get { throw new NotSupportedException(); }
 102		}
 103		
 104		/// <inheritdoc/>
 105		public override object[] GetCustomAttributes(bool inherit)
 106		{
 107			throw new NotSupportedException();
 108		}
 109		
 110		/// <inheritdoc/>
 111		public override object[] GetCustomAttributes(Type attributeType, bool inherit)
 112		{
 113			throw new NotSupportedException();
 114		}
 115		
 116		/// <inheritdoc/>
 117		public override bool IsDefined(Type attributeType, bool inherit)
 118		{
 119			return IsDefined(this, inherit, attributeType);
 120		}
 121		
 122		public static bool IsDefined(IDebugMemberInfo member, bool inherit, params Type[] attributeTypes)
 123		{
 124			if (inherit)
 125				throw new NotSupportedException("inherit");
 126			
 127			MetaDataImport metaData = member.DebugModule.MetaData;
 128			uint token = (uint)member.MetadataToken;
 129			foreach(CustomAttributeProps ca in metaData.EnumCustomAttributeProps(token, 0)) {
 130				CorTokenType tkType = (CorTokenType)(ca.Type & 0xFF000000);
 131				string attributeName;
 132				if (tkType == CorTokenType.MemberRef) {
 133					MemberRefProps constructorMethod = metaData.GetMemberRefProps(ca.Type);
 134					attributeName = metaData.GetTypeRefProps(constructorMethod.DeclaringType).Name;
 135				} else if (tkType == CorTokenType.MethodDef) {
 136					MethodProps constructorMethod = metaData.GetMethodProps(ca.Type);
 137					attributeName = metaData.GetTypeDefProps(constructorMethod.ClassToken).Name;
 138				} else {
 139					throw new DebuggerException("Not expected: " + tkType);
 140				}
 141				foreach(Type attributeType in attributeTypes) {
 142					if (attributeName == attributeType.FullName)
 143						return true;
 144				}
 145			}
 146			return false;
 147		}
 148		
 149		/// <inheritdoc/>
 150		public override Assembly Assembly {
 151			get { throw new NotSupportedException(); }
 152		}
 153		
 154		/// <inheritdoc/>
 155		public override string AssemblyQualifiedName {
 156			get { throw new NotSupportedException(); }
 157		}
 158		
 159		/// <inheritdoc/>
 160		public override Type BaseType {
 161			get {
 162				// corType.Base *sometimes* does not work for object and can cause "Value does not fall within the expected range." exception
 163				if (this.FullName == typeof(object).FullName) {
 164					return null;
 165				}
 166				// corType.Base does not work for arrays
 167				if (this.IsArray) {
 168					return DebugType.CreateFromType(this.AppDomain.Mscorlib, typeof(Array));
 169				}
 170				// corType.Base does not work for primitive types
 171//				if (this.IsPrimitive) {
 172//					return DebugType.CreateFromType(this.AppDomain, typeof(ValueType));
 173//				}
 174				if (this.IsPointer || corElementType == CorElementType.VOID) {
 175					return null;
 176				}
 177				ICorDebugType baseType = corType.GetBase();
 178				if (baseType != null) {
 179					return CreateFromCorType(this.AppDomain, baseType);
 180				} else {
 181					return null;
 182				}
 183			}
 184		}
 185		
 186		//		public virtual bool ContainsGenericParameters { get; }
 187		//		public virtual MethodBase DeclaringMethod { get; }
 188		
 189		/// <inheritdoc/>
 190		public override string FullName {
 191			get { return fullName; }
 192		}
 193		
 194		[Debugger.Tests.Ignore]
 195		public string FullNameWithoutGenericArguments {
 196			get { return fullNameWithoutGenericArguments; }
 197		}
 198		
 199		/// <inheritdoc/>
 200		public override Guid GUID {
 201			get { throw new NotSupportedException(); }
 202		}
 203		
 204		//		public virtual GenericParameterAttributes GenericParameterAttributes { get; }
 205		//		public virtual int GenericParameterPosition { get; }
 206		//		public virtual bool IsGenericParameter { get; }
 207		//		public virtual bool IsGenericTypeDefinition { get; }
 208		
 209		/// <inheritdoc/>
 210		public override bool IsGenericType {
 211			get {
 212				return this.GetGenericArguments().Length > 0;
 213			}
 214		}
 215		
 216		/// <inheritdoc/>
 217		public override string Namespace {
 218			get { return ns; }
 219		}
 220		
 221		//		public virtual StructLayoutAttribute StructLayoutAttribute { get; }
 222		
 223		/// <inheritdoc/>
 224		public override RuntimeTypeHandle TypeHandle {
 225			get { throw new NotSupportedException(); }
 226		}
 227		
 228		/// <inheritdoc/>
 229		public override Type UnderlyingSystemType {
 230			get { return this; }
 231		}
 232		
 233		/// <inheritdoc/>
 234		public override int GetArrayRank()
 235		{
 236			if (!IsArray) throw new ArgumentException("Type is not array");
 237			
 238			return (int)corType.GetRank();
 239		}
 240		
 241		/// <inheritdoc/>
 242		protected override TypeAttributes GetAttributeFlagsImpl()
 243		{
 244			return (TypeAttributes)classProps.Flags;
 245		}
 246		
 247		/// <inheritdoc/>
 248		protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
 249		{
 250			if (bindingAttr == BindingFlags.Default)
 251				bindingAttr = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
 252			MethodInfo ctor = GetMethodImpl(".ctor", bindingAttr, binder, callConvention, types, modifiers);
 253			if (ctor == null)
 254				return null;
 255			return new DebugConstructorInfo((DebugMethodInfo)ctor);
 256		}
 257		
 258		/// <inheritdoc/>
 259		public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
 260		{
 261			throw new NotSupportedException();
 262		}
 263		
 264		//		public virtual MemberInfo[] GetDefaultMembers();
 265		
 266		/// <inheritdoc/>
 267		public override Type GetElementType()
 268		{
 269			return elementType;
 270		}
 271		
 272		const BindingFlags SupportedFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy;
 273		
 274		/// <summary> Return member with the given token</summary>
 275		public MemberInfo GetMember(uint token)
 276		{
 277			return membersByToken[(int)token];
 278		}
 279		
 280		/// <summary> Return member with the given token</summary>
 281		public bool TryGetMember(uint token, out MemberInfo memberInfo)
 282		{
 283			return membersByToken.TryGetValue((int)token, out memberInfo);
 284		}
 285		
 286		public T GetMember<T>(string name, BindingFlags bindingFlags, Predicate<T> filter) where T:MemberInfo
 287		{
 288			T[] res = GetMembers<T>(name, bindingFlags, filter);
 289			if (res.Length > 0) {
 290				return res[0];
 291			} else {
 292				return null;
 293			}
 294		}
 295		
 296		/// <remarks>
 297		/// Note that at the moment the function will return two methods for interface implementations:
 298		/// the acutual implementation and the method in the interface
 299		/// </remarks>
 300		public T[] GetMembers<T>(string name, BindingFlags bindingFlags, Predicate<T> filter) where T:MemberInfo
 301		{
 302			BindingFlags unsupported = bindingFlags & ~SupportedFlags;
 303			if (unsupported != 0)
 304				throw new NotSupportedException("BindingFlags: " + unsupported);
 305			
 306			if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == 0)
 307				throw new ArgumentException("Public or NonPublic flag must be included", "bindingFlags");
 308			
 309			if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == 0)
 310				throw new ArgumentException("Instance or Static flag must be included", "bindingFlags");
 311			
 312			// Filter by name
 313			IEnumerable<List<MemberInfo>> searchScope;
 314			if (name != null) {
 315				if (membersByName.ContainsKey(name)) {
 316					searchScope = new List<MemberInfo>[] { membersByName[name] };
 317				} else {
 318					searchScope = new List<MemberInfo>[] { };
 319				}
 320			} else {
 321				searchScope = membersByName.Values;
 322			}
 323			
 324			List<T> results = new List<T>();
 325			foreach(List<MemberInfo> memberInfos in searchScope) {
 326				foreach(MemberInfo memberInfo in memberInfos) {
 327					// Filter by type
 328					if (!(memberInfo is T)) continue; // Reject item
 329					
 330					// Filter by access
 331					if (((IDebugMemberInfo)memberInfo).IsPublic) {
 332						if ((bindingFlags & BindingFlags.Public) == 0) continue; // Reject item
 333					} else {
 334						if ((bindingFlags & BindingFlags.NonPublic) == 0) continue; // Reject item
 335					}
 336					
 337					// Filter by static / instance
 338					if (((IDebugMemberInfo)memberInfo).IsStatic) {
 339						if ((bindingFlags & BindingFlags.Static) == 0) continue; // Reject item
 340					} else {
 341						if ((bindingFlags & BindingFlags.Instance) == 0) continue; // Reject item
 342					}
 343					
 344					// Filter using predicate
 345					if (filter != null && !filter((T)memberInfo)) continue; // Reject item
 346					
 347					results.Add((T)memberInfo);
 348				}
 349			}
 350			
 351			if ((bindingFlags & BindingFlags.DeclaredOnly) == 0) {
 352				// Query supertype
 353				if (this.BaseType != null) {
 354					if ((bindingFlags & BindingFlags.FlattenHierarchy) == 0) {
 355						// Do not include static types
 356						bindingFlags = bindingFlags & ~BindingFlags.Static;
 357					}
 358					// Any flags left?
 359					if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) != 0) {
 360						T[] superResults = ((DebugType)this.BaseType).GetMembers<T>(name, bindingFlags, filter);
 361						results.AddRange(superResults);
 362					}
 363				}
 364				// Query interfaces - needed to get inherited methods of an interface
 365				if (this.IsInterface) {
 366					foreach (DebugType inter in this.GetInterfaces()) {
 367						// GetInterfaces will return all interfaces - no need to recurse
 368						bindingFlags |= BindingFlags.DeclaredOnly;
 369						T[] interResults = inter.GetMembers<T>(name, bindingFlags, filter);
 370						results.AddRange(interResults);
 371					}
 372				}
 373			}
 374			
 375			return results.ToArray();
 376		}
 377		
 378		MemberInfo SelectOverload(MemberInfo[] candidates, Type[] argumentTypes)
 379		{
 380			if (candidates.Length == 0)
 381				return null;
 382			if (candidates.Length == 1) {
 383				if (argumentTypes == null)
 384					return candidates[0];
 385				ParameterInfo[] pars = ((IOverloadable)candidates[0]).GetParameters();
 386				if (pars.Length != argumentTypes.Length)
 387					throw new GetValueException("Incorrect parameter count");
 388				for(int i = 0; i < pars.Length; i++) {
 389					ParameterInfo par = pars[i];
 390					if (!((DebugType)argumentTypes[i]).CanImplicitelyConvertTo(par.ParameterType))
 391						throw new GetValueException("Incorrect parameter type for '{0}'. Excpeted {1}, seen {2}", par.Name, par.ParameterType.FullName, argumentTypes[i]);
 392				}
 393				return candidates[0];
 394			}
 395			
 396			List<MemberInfo> applicable = new List<MemberInfo>();
 397			foreach(MemberInfo candidate in candidates) {
 398				bool isExactMatch;
 399				if (IsApplicable(((IOverloadable)candidate).GetParameters(), argumentTypes, out isExactMatch))
 400					applicable.Add(candidate);
 401				if (isExactMatch)
 402					return candidate;
 403			}
 404			if (applicable.Count == 0) {
 405				throw new GetValueException("No applicable overload found");
 406			} else if (applicable.Count == 1) {
 407				return applicable[0];
 408			} else {
 409				// Remove base class definitions
 410				IntPtr sig = ((IOverloadable)applicable[0]).GetSignarture();
 411				for(int i = 1; i < applicable.Count;) {
 412					if (sig == ((IOverloadable)applicable[i]).GetSignarture()) {
 413						applicable.RemoveAt(i);
 414					} else {
 415						i++;
 416					}
 417				}
 418				if (applicable.Count == 1)
 419					return applicable[0];
 420				StringBuilder overloads = new StringBuilder();
 421				foreach(MemberInfo app in applicable) {
 422					overloads.Append(Environment.NewLine);
 423					overloads.Append("  ");
 424					overloads.Append(app.ToString());
 425				}
 426				throw new GetValueException("More then one applicable overload found:" + overloads.ToString());
 427			}
 428		}
 429		
 430		bool IsApplicable(ParameterInfo[] parameters, Type[] argumentTypes, out bool isExactMatch)
 431		{
 432			isExactMatch = false;
 433			if (argumentTypes == null)
 434				return true;
 435			if (argumentTypes.Length != parameters.Length)
 436				return false;
 437			isExactMatch = true;
 438			for(int i = 0; i < parameters.Length; i++) {
 439				if (argumentTypes[i] != parameters[i].ParameterType) {
 440					isExactMatch = false;
 441					if (!((DebugType)argumentTypes[i]).CanImplicitelyConvertTo(parameters[i].ParameterType))
 442						return false;
 443				}
 444			}
 445			return true;
 446		}
 447		
 448		static string Byte    = typeof(byte).FullName;
 449		static string Short   = typeof(short).FullName;
 450		static string Int     = typeof(int).FullName;
 451		static string Long    = typeof(long).FullName;
 452		static string SByte   = typeof(sbyte).FullName;
 453		static string UShort  = typeof(ushort).FullName;
 454		static string UInt    = typeof(uint).FullName;
 455		static string ULong   = typeof(ulong).FullName;
 456		static string Float   = typeof(float).FullName;
 457		static string Double  = typeof(double).FullName;
 458		static string Char    = typeof(char).FullName;
 459		static string Decimal = typeof(decimal).FullName;
 460		
 461		public bool CanImplicitelyConvertTo(Type toType)
 462		{
 463			if (this == toType)
 464				return true;
 465			if (this.IsPrimitive && toType.IsPrimitive) {
 466				string f = this.FullName;
 467				string t = toType.FullName;
 468				if (f == t)
 469					return true;
 470				if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
 471					return true;
 472				if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
 473					return true;
 474				if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
 475					return true;
 476				if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
 477					return true;
 478				if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
 479					return true;
 480				if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
 481					return true;
 482				if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
 483					return true;
 484				if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
 485					return true;
 486				if (f == Float && t == Double)
 487					return true;
 488				return false;
 489			} else {
 490				return toType.IsAssignableFrom(this);
 491			}
 492		}
 493		
 494		/// <inheritdoc/>
 495		public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
 496		{
 497			throw new NotSupportedException();
 498		}
 499		
 500		//		public virtual EventInfo[] GetEvents();
 501		
 502		/// <inheritdoc/>
 503		public override EventInfo[] GetEvents(BindingFlags bindingAttr)
 504		{
 505			throw new NotSupportedException();
 506		}
 507		
 508		/// <inheritdoc/>
 509		public override FieldInfo GetField(string name, BindingFlags bindingAttr)
 510		{
 511			return GetMember<FieldInfo>(name, bindingAttr, null);
 512		}
 513		
 514		/// <inheritdoc/>
 515		public override FieldInfo[] GetFields(BindingFlags bindingAttr)
 516		{
 517			return GetMembers<FieldInfo>(null, bindingAttr, null);
 518		}
 519		
 520		/// <inheritdoc/>
 521		public override Type[] GetGenericArguments()
 522		{
 523			return genericArguments.ToArray();
 524		}
 525		
 526		internal ICorDebugType[] GenericArgumentsAsCorDebugType {
 527			get {
 528				List<ICorDebugType> types = new List<ICorDebugType>();
 529				foreach(DebugType arg in GetGenericArguments()) {
 530					types.Add(arg.CorType);
 531				}
 532				return types.ToArray();
 533			}
 534		}
 535		
 536		//		public virtual Type[] GetGenericParameterConstraints();
 537		//		public virtual Type GetGenericTypeDefinition();
 538		
 539		/// <inheritdoc/>
 540		public override Type GetInterface(string name, bool ignoreCase)
 541		{
 542			foreach(DebugType inter in this.GetInterfaces()) {
 543				if (string.Equals(inter.FullName, name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal))
 544					return inter;
 545				if (string.Equals(inter.FullNameWithoutGenericArguments, name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal))
 546					return inter;
 547			}
 548			if (BaseType != null) {
 549				return BaseType.GetInterface(fullName);
 550			} else {
 551				return null;
 552			}
 553		}
 554		
 555		//		public virtual InterfaceMapping GetInterfaceMap(Type interfaceType);
 556		
 557		/// <inheritdoc/>
 558		/// <returns> All interfaces implemented by the type </returns>
 559		public override Type[] GetInterfaces()
 560		{
 561			return this.interfaces.ToArray();
 562		}
 563		
 564		/// <inheritdoc/>
 565		public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
 566		{
 567			return GetMembers<MemberInfo>(name, bindingAttr, delegate(MemberInfo info) { return (info.MemberType & type) != 0; });
 568		}
 569		
 570		/// <inheritdoc/>
 571		public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
 572		{
 573			return GetMembers<MemberInfo>(null, bindingAttr, null);
 574		}
 575		
 576		/// <summary> Return method with the given token</summary>
 577		public MethodInfo GetMethod(uint token)
 578		{
 579			return (MethodInfo)membersByToken[(int)token];
 580		}
 581		
 582		/// <summary> Return method overload with given parameter names </summary>
 583		/// <returns> Null if not found </returns>
 584		public MethodInfo GetMethod(string name, string[] paramNames)
 585		{
 586			foreach(DebugMethodInfo candidate in GetMembers<DebugMethodInfo>(name, BindingFlagsAll, null)) {
 587				if (candidate.ParameterCount == paramNames.Length) {
 588					bool match = true;
 589					for(int i = 0; i < paramNames.Length; i++) {
 590						if (paramNames[i] != candidate.GetParameters()[i].Name)
 591							match = false;
 592					}
 593					if (match)
 594						return candidate;
 595				}
 596			}
 597			return null;
 598		}
 599		
 600		/// <inheritdoc/>
 601		protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] paramTypes, ParameterModifier[] modifiers)
 602		{
 603			if (binder != null)
 604				throw new NotSupportedException("binder");
 605			if (callConvention != CallingConventions.Any)
 606				throw new NotSupportedException("callConvention");
 607			if (modifiers != null)
 608				throw new NotSupportedException("modifiers");
 609			
 610			MethodInfo[] candidates = GetMethods(name, bindingAttr);
 611			return (MethodInfo)SelectOverload(candidates, paramTypes);
 612		}
 613		
 614		public MethodInfo[] GetMethods(string name, BindingFlags bindingAttr)
 615		{
 616			return GetMembers<MethodInfo>(name, bindingAttr, null);
 617		}
 618		
 619		/// <inheritdoc/>
 620		public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
 621		{
 622			return GetMembers<MethodInfo>(null, bindingAttr, null);
 623		}
 624		
 625		/// <inheritdoc/>
 626		public override Type GetNestedType(string name, BindingFlags bindingAttr)
 627		{
 628			throw new NotSupportedException();
 629		}
 630		
 631		/// <inheritdoc/>
 632		public override Type[] GetNestedTypes(BindingFlags bindingAttr)
 633		{
 634			throw new NotSupportedException();
 635		}
 636		
 637		public MemberInfo[] GetFieldsAndNonIndexedProperties(BindingFlags bindingAttr)
 638		{
 639			return GetMembers<MemberInfo>(null, bindingAttr, IsFieldOrNonIndexedProperty);
 640		}
 641		
 642		public static bool IsFieldOrNonIndexedProperty(MemberInfo info)
 643		{
 644			if (info is FieldInfo)
 645				return true;
 646			if (info is PropertyInfo) {
 647				return ((PropertyInfo)info).GetGetMethod(true) != null &&
 648				       ((PropertyInfo)info).GetGetMethod(true).GetParameters().Length == 0;
 649			}
 650			return false;
 651		}
 652		
 653		public PropertyInfo[] GetProperties(string name, BindingFlags bindingAttr)
 654		{
 655			return GetMembers<PropertyInfo>(name, bindingAttr, null);
 656		}
 657		
 658		/// <inheritdoc/>
 659		public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
 660		{
 661			return GetMembers<PropertyInfo>(null, bindingAttr, null);
 662		}
 663		
 664		/// <inheritdoc/>
 665		protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] paramTypes, ParameterModifier[] modifiers)
 666		{
 667			if (binder != null)
 668				throw new NotSupportedException("binder");
 669			if (returnType != null)
 670				throw new NotSupportedException("returnType");
 671			if (modifiers != null)
 672				throw new NotSupportedException("modifiers");
 673			
 674			PropertyInfo[] candidates = GetProperties(name, bindingAttr);
 675			return (PropertyInfo)SelectOverload(candidates, paramTypes);
 676		}
 677		
 678		/// <inheritdoc/>
 679		protected override bool HasElementTypeImpl()
 680		{
 681			return elementType != null;
 682		}
 683		
 684		/// <inheritdoc/>
 685		public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
 686		{
 687			throw new NotSupportedException();
 688		}
 689		
 690		/// <inheritdoc/>
 691		protected override bool IsArrayImpl()
 692		{
 693			return corElementType == CorElementType.ARRAY ||
 694			       corElementType == CorElementType.SZARRAY;
 695		}
 696		
 697		/// <inheritdoc/>
 698		protected override bool IsByRefImpl()
 699		{
 700			return corElementType == CorElementType.BYREF;
 701		}
 702		
 703		/// <inheritdoc/>
 704		protected override bool IsPointerImpl()
 705		{
 706			return corElementType == CorElementType.PTR;
 707		}
 708		
 709//		public bool IsClass {
 710//			get {
 711//				return !this.IsInterface && !this.IsSubclassOf(valueType);
 712//			}
 713//		}
 714//		
 715//		public bool IsInterface {
 716//			get {
 717//				return ((this.GetAttributeFlagsImpl() & TypeAttributes.Interface) != 0);
 718//			}
 719//		}
 720		
 721		/// <inheritdoc/>
 722		protected override bool IsValueTypeImpl()
 723		{
 724			// ValueType and Enum are exceptions and are threated as classes
 725			return this.FullName != typeof(ValueType).FullName &&
 726			       this.FullName != typeof(Enum).FullName &&
 727			       this.IsSubclassOf(DebugType.CreateFromType(this.AppDomain.Mscorlib, typeof(ValueType)));
 728		}
 729		
 730		/// <inheritdoc/>
 731		public override bool IsSubclassOf(Type superType)
 732		{
 733			if (!(superType is DebugType)) {
 734				superType = CreateFromType(this.AppDomain, superType);
 735			}
 736			return base.IsSubclassOf(superType);
 737		}
 738		
 739		/// <inheritdoc/>
 740		protected override bool IsCOMObjectImpl()
 741		{
 742			throw new NotSupportedException();
 743		}
 744		
 745		/// <inheritdoc/>
 746		public override bool IsInstanceOfType(object o)
 747		{
 748			if (o == null) return false;
 749			if (!(o is Value)) return false;
 750			return this.IsAssignableFrom(((Value)o).Type);
 751		}
 752		
 753		/// <inheritdoc/>
 754		public override bool IsAssignableFrom(Type c)
 755		{
 756			if (this == c) return true;
 757			if (this.IsInterface) {
 758				foreach(Type intf in c.GetInterfaces()) {
 759					if (this == intf)
 760						return true;
 761				}
 762				return false;
 763			} else {
 764				return c.IsSubclassOf(this);
 765			}
 766		}
 767		
 768		//		protected virtual bool IsContextfulImpl();
 769		//		protected virtual bool IsMarshalByRefImpl();
 770		
 771		/// <summary> Returns simple managed type coresponding to the primitive type. </summary>
 772		[Debugger.Tests.Ignore]
 773		public System.Type PrimitiveType {
 774			get { return primitiveType; }
 775		}
 776		
 777		/// <inheritdoc/>
 778		protected override bool IsPrimitiveImpl()
 779		{
 780			return this.PrimitiveType != null;
 781		}
 782		
 783		/// <summary> Gets a value indicating whether the type is an integer type </summary>
 784		public bool IsInteger {
 785			get {
 786				switch (this.FullName) {
 787					case "System.SByte":
 788					case "System.Byte":
 789					case "System.Int16":
 790					case "System.UInt16":
 791					case "System.Int32":
 792					case "System.UInt32":
 793					case "System.Int64":
 794					case "System.UInt64": return true;
 795					default: return false;
 796				}
 797			}
 798		}
 799		
 800		public bool IsCompilerGenerated {
 801			get {
 802				return IsDefined(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false);
 803			}
 804		}
 805		
 806		public bool IsDisplayClass {
 807			get {
 808				return this.Name.StartsWith("<>") && this.Name.Contains("__DisplayClass");
 809			}
 810		}
 811		
 812		public bool IsYieldEnumerator {
 813			get {
 814				if (this.IsCompilerGenerated) {
 815					return GetInterface(typeof(System.Collections.IEnumerator).FullName) != null;
 816				}
 817				return false;
 818			}
 819		}
 820		
 821		bool IDebugMemberInfo.IsAssembly {
 822			get { return false; }
 823		}
 824		
 825		bool IDebugMemberInfo.IsFamily {
 826			get { return false; }
 827		}
 828		
 829		bool IDebugMemberInfo.IsPrivate {
 830			get { return this.IsNotPublic; }
 831		}
 832		
 833		bool IDebugMemberInfo.IsStatic {
 834			get { return false; }
 835		}
 836		
 837		public static DebugType CreateFromTypeDefOrRef(Module module, bool? valueType, uint token, DebugType[] genericArguments)
 838		{
 839			CorTokenType tkType = (CorTokenType)(token & 0xFF000000);
 840			if (tkType == CorTokenType.TypeDef) {
 841				ICorDebugClass corClass = module.CorModule.GetClassFromToken(token);
 842				return CreateFromCorClass(module.AppDomain, valueType, corClass, genericArguments);
 843			} else if (tkType == CorTokenType.TypeRef) {
 844				TypeRefProps refProps = module.MetaData.GetTypeRefProps(token);
 845				string fullName = refProps.Name;
 846				CorTokenType scopeType = (CorTokenType)(refProps.ResolutionScope & 0xFF000000);
 847				DebugType enclosingType = null;
 848				if (scopeType == CorTokenType.TypeDef || scopeType == CorTokenType.TypeRef) {
 849					// Resolve the enclosing TypeRef in this scope
 850					enclosingType = CreateFromTypeDefOrRef(module, null, refProps.ResolutionScope, genericArguments);
 851				}
 852				return CreateFromName(module.AppDomain, fullName, enclosingType, genericArguments);
 853			} else {
 854				throw new DebuggerException("TypeDef or TypeRef expected.  Seen " + tkType);
 855			}
 856		}
 857		
 858		public static DebugType CreateFromType(Module module, System.Type type)
 859		{
 860			if (type is DebugType)
 861				throw new DebuggerException("You already have DebugType, no need to create it.");
 862			if (type.GetGenericArguments().Length > 0)
 863				throw new DebuggerException("Generic arguments not allowed in this overload");
 864			
 865			if (module.LoadedDebugTypes.ContainsKey(type.FullName))
 866				return module.LoadedDebugTypes[type.FullName];
 867			
 868			DebugType declaringType = null;
 869			if (type.DeclaringType != null)
 870				declaringType = CreateFromType(module, type.DeclaringType);
 871			
 872			return CreateFromName(module, type.FullName, declaringType);
 873		}
 874		
 875		public static DebugType CreateFromType(AppDomain appDomain, System.Type type, params DebugType[] genericArgumentsOverride)
 876		{
 877			if (type is DebugType)
 878				throw new DebuggerException("You already have DebugType, no need to create it.");
 879			
 880			// Get generic arguments for the type if they are not explicitely defined
 881			if (genericArgumentsOverride == null) {
 882				List<DebugType> genArgs = new List<DebugType>();
 883				foreach(System.Type arg in type.GetGenericArguments()) {
 884					genArgs.Add(CreateFromType(appDomain, arg, null /* implicit */));
 885				}
 886				genericArgumentsOverride = genArgs.ToArray();
 887			}
 888			
 889			string name;
 890			DebugType declaringType;
 891			if (type.DeclaringType != null) {
 892				name = type.Name;
 893				declaringType = CreateFromType(appDomain, type.DeclaringType, genericArgumentsOverride);
 894			} else {
 895				name = string.IsNullOrEmpty(type.Namespace) ? type.Name : type.Namespace + "." + type.Name;
 896				declaringType = null;
 897			}
 898			
 899			return CreateFromName(appDomain, name, declaringType, genericArgumentsOverride);
 900		}
 901		
 902		public static DebugType CreateFromName(AppDomain appDomain, string name, DebugType declaringType, params DebugType[] genericArguments)
 903		{
 904			DebugType type = CreateFromNameOrNull(appDomain, name, declaringType, genericArguments);
 905			if (type == null)
 906				throw new DebuggerException("Type not found: " + name + (declaringType != null ? " (declaring type = " + declaringType.FullName + ")" : string.Empty));
 907			return type;
 908		}
 909		
 910		public static DebugType CreateFromNameOrNull(AppDomain appDomain, string name, DebugType declaringType, params DebugType[] genericArguments)
 911		{
 912			if (declaringType != null)
 913				return CreateFromNameOrNull(declaringType.DebugModule, name, declaringType, genericArguments);
 914			foreach(Module module in appDomain.Process.Modules) {
 915				if (module.AppDomain != appDomain) continue;
 916				DebugType result = CreateFromNameOrNull(module, name, declaringType, genericArguments);
 917				if (result != null)
 918					return result;
 919			}
 920			return null;
 921		}
 922		
 923		public static DebugType CreateFromName(Module module, string name, DebugType declaringType, params DebugType[] genericArguments)
 924		{
 925			DebugType type = CreateFromNameOrNull(module, name, declaringType, genericArguments);
 926			if (type == null)
 927				throw new DebuggerException("Type not found: " + name + (declaringType != null ? " (declaring type = " + declaringType.FullName + ")" : string.Empty));
 928			return type;
 929		}
 930		
 931		public static DebugType CreateFromNameOrNull(Module module, string name, DebugType declaringType, params DebugType[] genericArguments)
 932		{
 933			if (declaringType != null && declaringType.DebugModule != module)
 934				throw new DebuggerException("Declaring type must be in the same module");
 935			
 936			uint token;
 937			try {
 938				token = module.MetaData.FindTypeDefPropsByName(name, declaringType == null ? 0 : (uint)declaringType.MetadataToken).Token;
 939			} catch {
 940				return null;
 941			}
 942			return CreateFromTypeDefOrRef(module, null, token, genericArguments);
 943		}
 944		
 945		public static DebugType CreateFromTypeSpec(Module module, uint token, DebugType declaringType)
 946		{
 947			CorTokenType tokenType = (CorTokenType)(token & 0xFF000000);
 948			if (tokenType != CorTokenType.TypeSpec) {
 949				throw new DebuggerException("TypeSpec expected.  Seen " + tokenType);
 950			}
 951			
 952			byte[] typeSpecBlob = module.MetaData.GetTypeSpecFromToken(token).GetData();
 953			return CreateFromSignature(module, typeSpecBlob, declaringType);
 954		}
 955		
 956		public static DebugType CreateFromSignature(Module module, byte[] signature, DebugType declaringType)
 957		{
 958			SignatureReader sigReader = new SignatureReader(signature);
 959			int start;
 960			SigType sigType = sigReader.ReadType(signature, 0, out start);
 961			return CreateFromSignature(module, sigType, declaringType);
 962		}
 963		
 964		internal static DebugType CreateFromSignature(Module module, SigType sigType, DebugType declaringType)
 965		{
 966			System.Type sysType = CorElementTypeToManagedType((CorElementType)(uint)sigType.ElementType);
 967			if (sysType != null)
 968				return CreateFromType(module.AppDomain.Mscorlib, sysType);
 969			
 970			if (sigType is CLASS) {
 971				return CreateFromTypeDefOrRef(module, false, ((CLASS)sigType).Type.ToUInt(), null);
 972			}
 973			
 974			if (sigType is VALUETYPE) {
 975				return CreateFromTypeDefOrRef(module, true, ((VALUETYPE)sigType).Type.ToUInt(), null);
 976			}
 977			
 978			// Numbered generic reference
 979			if (sigType is VAR) {
 980				if (declaringType == null) throw new DebuggerException("declaringType is needed");
 981				return (DebugType)declaringType.GetGenericArguments()[((VAR)sigType).Index];
 982			}
 983			
 984			// Numbered generic reference
 985			if (sigType is MVAR) {
 986				return module.AppDomain.ObjectType;
 987			}
 988			
 989			if (sigType is GENERICINST) {
 990				GENERICINST genInst = (GENERICINST)sigType;
 991				
 992				List<DebugType> genArgs = new List<DebugType>(genInst.Signature.Arity);
 993				foreach(GenericArg genArgSig in genInst.Signature.Types) {
 994					genArgs.Add(CreateFromSignature(module, genArgSig.Type, declaringType));
 995				}
 996				
 997				return CreateFromTypeDefOrRef(module, genInst.ValueType, genInst.Type.ToUInt(), genArgs.ToArray());
 998			}
 999			
1000			if (sigType is ARRAY) {
1001				ARRAY arraySig = (ARRAY)sigType;
1002				DebugType elementType = CreateFromSignature(module, arraySig.Type, declaringType);
1003				return (DebugType)elementType.MakeArrayType(arraySig.Shape.Rank);
1004			}
1005			
1006			if (sigType is SZARRAY) {
1007				SZARRAY arraySig = (SZARRAY)sigType;
1008				DebugType elementType = CreateFromSignature(module, arraySig.Type, declaringType);
1009				return (DebugType)elementType.MakeArrayType();
1010			}
1011			
1012			if (sigType is PTR) {
1013				PTR ptrSig = (PTR)sigType;
1014				DebugType elementType;
1015				if (ptrSig.Void) {
1016					elementType = DebugType.CreateFromType(module.AppDomain.Mscorlib, typeof(void));
1017				} else {
1018					elementType = CreateFromSignature(module, ptrSig.PtrType, declaringType);
1019				}
1020				return (DebugType)elementType.MakePointerType();
1021			}
1022			
1023			if (sigType is FNPTR) {
1024				// TODO: FNPTR
1025			}
1026			
1027			throw new NotImplementedException(sigType.ElementType.ToString());
1028		}
1029		
1030		// public virtual Type MakeGenericType(params Type[] typeArguments);
1031		
1032		/// <inheritdoc/>
1033		public override Type MakeArrayType(int rank)
1034		{
1035			ICorDebugType res = this.AppDomain.CorAppDomain2.GetArrayOrPointerType((uint)CorElementType.ARRAY, (uint)rank, this.CorType);
1036			return CreateFromCorType(this.AppDomain, res);
1037		}
1038		
1039		/// <inheritdoc/>
1040		public override Type MakeArrayType()
1041		{
1042			ICorDebugType res = this.AppDomain.CorAppDomain2.GetArrayOrPointerType((uint)CorElementType.SZARRAY, 1, this.CorType);
1043			return CreateFromCorType(this.AppDomain, res);
1044		}
1045		
1046		/// <inheritdoc/>
1047		public override Type MakePointerType()
1048		{
1049			ICorDebugType res = this.AppDomain.CorAppDomain2.GetArrayOrPointerType((uint)CorElementType.PTR, 0, this.CorType);
1050			return CreateFromCorType(this.AppDomain, res);
1051		}
1052		
1053		/// <inheritdoc/>
1054		public override Type MakeByRefType()
1055		{
1056			ICorDebugType res = this.AppDomain.CorAppDomain2.GetArrayOrPointerType((uint)CorElementType.BYREF, 0, this.CorType);
1057			return CreateFromCorType(this.AppDomain, res);
1058		}
1059		
1060		public static DebugType CreateFromCorClass(AppDomain appDomain, bool? valueType, ICorDebugClass corClass, DebugType[] genericArguments)
1061		{
1062			MetaDataImport metaData = appDomain.Process.Modules[corClass.GetModule()].MetaData;
1063			
1064			if (valueType == null) {
1065				uint superClassToken = metaData.GetTypeDefProps(corClass.GetToken()).SuperClassToken;
1066				CorTokenType tkType = (CorTokenType)(superClassToken & 0xFF000000);
1067				if (tkType == CorTokenType.TypeDef) {
1068					valueType = metaData.GetTypeDefProps(superClassToken).Name == typeof(ValueType).FullName;
1069				}
1070				if (tkType == CorTokenType.TypeRef) {
1071					valueType = metaData.GetTypeRefProps(superClassToken).Name == typeof(ValueType).FullName;
1072				}
1073				if (tkType == CorTokenType.TypeSpec) {
1074					valueType = false; // TODO: Resolve properly
1075				}
1076			}
1077			
1078			genericArguments = genericArguments ?? new DebugType[] {};
1079			if (genericArguments.Length < metaData.EnumGenericParams(corClass.GetToken()).Length) {
1080				throw new DebuggerException("Not enough generic arguments");
1081			}
1082			Array.Resize(ref genericArguments, metaData.EnumGenericParams(corClass.GetToken()).Length);
1083			
1084			List<ICorDebugType> corGenArgs = new List<ICorDebugType>(genericArguments.Length);
1085			foreach(DebugType genAgr in genericArguments) {
1086				corGenArgs.Add(genAgr.CorType);
1087			}
1088			
1089			ICorDebugType corType = ((ICorDebugClass2)corClass).GetParameterizedType((uint)(valueType.Value ? CorElementType.VALUETYPE : CorElementType.CLASS), corGenArgs.ToArray());
1090			
1091			return CreateFromCorType(appDomain, corType);
1092		}
1093		
1094		/// <summary> Obtains instance of DebugType. Same types will return identical instance. </summary>
1095		public static DebugType CreateFromCorType(AppDomain appDomain, ICorDebugType corType)
1096		{
1097			if (appDomain.DebugTypeCache.ContainsKey(corType))
1098				return appDomain.DebugTypeCache[corType];
1099			
1100			// Convert short-form to class-form
1101			Type primitiveType = CorElementTypeToManagedType((CorElementType)(corType.GetTheType()));
1102			if (primitiveType != null) {
1103				DebugType type = CreateFromType(appDomain.Mscorlib, primitiveType);
1104				// Use cache next time
1105				appDomain.DebugTypeCache[corType] = type;
1106				return type;
1107			} else {
1108				DebugType type = new DebugType(appDomain, corType);
1109				// Ensure name-identity
1110				if (type.DebugModule.LoadedDebugTypes.ContainsKey(type.FullName)) {
1111					type = type.DebugModule.LoadedDebugTypes[type.FullName];
1112					// corDebug cache needs to be fixed to this type - we do not want the semi-loaded type there
1113					appDomain.DebugTypeCache[corType] = type;
1114				} else {
1115					type.LoadMembers();
1116					type.DebugModule.LoadedDebugTypes[type.FullName] = type;
1117				}
1118				return type;
1119			}
1120		}
1121		
1122		DebugType(AppDomain appDomain, ICorDebugType corType)
1123		{
1124			if (corType == null)
1125				throw new ArgumentNullException("corType");
1126			
1127			this.corType = corType;
1128			this.corElementType = (CorElementType)corType.GetTheType();
1129			
1130			// Loading might access the type again
1131			appDomain.DebugTypeCache[corType] = this;
1132			
1133			if (corElementType == CorElementType.ARRAY ||
1134			    corElementType == CorElementType.SZARRAY ||
1135			    corElementType == CorElementType.PTR ||
1136			    corElementType == CorElementType.BYREF)
1137			{
1138				// CorDebugClass for arrays "is not loaded" and can not be used
1139				this.elementType = CreateFromCorType(appDomain, corType.GetFirstTypeParameter());
1140				this.module = appDomain.Mscorlib;
1141				this.classProps = new TypeDefProps();
1142				// Get names
1143				string suffix = string.Empty;
1144				if (corElementType == CorElementType.SZARRAY) suffix = "[]";
1145				if (corElementType == CorElementType.ARRAY)   suffix = "[" + new String(',', GetArrayRank() - 1) + "]";
1146				if (corElementType == CorElementType.PTR)     suffix = "*";
1147				if (corElementType == CorElementType.BYREF)   suffix = "&";
1148				this.ns = this.GetElementType().Namespace;
1149				this.name = this.GetElementType().Name + suffix;
1150				this.fullNameWithoutGenericArguments = ((DebugType)this.GetElementType()).FullNameWithoutGenericArguments + suffix;
1151				this.fullName = this.GetElementType().FullName + suffix;
1152			}
1153			
1154			if (corElementType == CorElementType.CLASS ||
1155			    corElementType == CorElementType.VALUETYPE)
1156			{
1157				// Get generic arguments
1158				foreach(ICorDebugType t in corType.EnumerateTypeParameters().GetEnumerator()) {
1159					genericArguments.Add(DebugType.CreateFromCorType(appDomain, t));
1160				}
1161				// Get class props
1162				this.module = appDomain.Process.Modules[corType.GetClass().GetModule()];
1163				this.classProps = module.MetaData.GetTypeDefProps(corType.GetClass().GetToken());
1164				if (this.DebugModule.AppDomain != appDomain)
1165					throw new DebuggerException("The specified AppDomain was inccorect");
1166				// Get the enclosing class
1167				if (!this.IsPublic && !this.IsNotPublic) {
1168					uint enclosingTk = module.MetaData.GetNestedClassProps((uint)this.MetadataToken).EnclosingClass;
1169					this.declaringType = DebugType.CreateFromTypeDefOrRef(this.DebugModule, null, enclosingTk, genericArguments.ToArray());
1170				}
1171				// Get names (it depends on the previous steps)
1172				int index = classProps.Name.LastIndexOf('.');
1173				if (index == -1) {
1174					this.ns = string.Empty;
1175					this.name = classProps.Name;
1176				} else {
1177					this.ns = classProps.Name.Substring(0, index);
1178					this.name = classProps.Name.Substring(index + 1);
1179				}
1180				LoadFullName();
1181				this.primitiveType = GetPrimitiveType(this.FullName);
1182			}
1183			
1184			if (module == null)
1185				throw new DebuggerException("Unexpected: " + corElementType);
1186		}
1187		
1188		internal static Type CorElementTypeToManagedType(CorElementType corElementType)
1189		{
1190			switch(corElementType) {
1191				case CorElementType.BOOLEAN: return typeof(System.Boolean);
1192				case CorElementType.CHAR:    return typeof(System.Char);
1193				case CorElementType.I1:      return typeof(System.SByte);
1194				case CorElementType.U1:      return typeof(System.Byte);
1195				case CorElementType.I2:      return typeof(System.Int16);
1196				case CorElementType.U2:      return typeof(System.UInt16);
1197				case CorElementType.I4:      return typeof(System.Int32);
1198				case CorElementType.U4:      return typeof(System.UInt32);
1199				case CorElementType.I8:      return typeof(System.Int64);
1200				case CorElementType.U8:      return typeof(System.UInt64);
1201				case CorElementType.R4:      return typeof(System.Single);
1202				case CorElementType.R8:      return typeof(System.Double);
1203				case CorElementType.I:       return typeof(System.IntPtr);
1204				case CorElementType.U:       return typeof(System.UIntPtr);
1205				case CorElementType.STRING:  return typeof(System.String);
1206				case CorElementType.OBJECT:  return typeof(System.Object);
1207				case CorElementType.VOID:    return typeof(void);
1208				default: return null;
1209			}
1210		}
1211		
1212		static Type GetPrimitiveType(string fullname)
1213		{
1214			switch (fullname) {
1215				case "System.Boolean": return typeof(System.Boolean);
1216				case "System.Char":    return typeof(System.Char);
1217				case "System.SByte":   return typeof(System.SByte);
1218				case "System.Byte":    return typeof(System.Byte);
1219				case "System.Int16":   return typeof(System.Int16);
1220				case "System.UInt16":  return typeof(System.UInt16);
1221				case "System.Int32":   return typeof(System.Int32);
1222				case "System.UInt32":  return typeof(System.UInt32);
1223				case "System.Int64":   return typeof(System.Int64);
1224				case "System.UInt64":  return typeof(System.UInt64);
1225				case "System.Single":  return typeof(System.Single);
1226				case "System.Double":  return typeof(System.Double);
1227				// String is not primitive type
1228				default: return null;
1229			}
1230		}
1231		
1232		void LoadFullName()
1233		{
1234			StringBuilder sb = new StringBuilder();
1235			
1236			if (declaringType != null) {
1237				sb.Append(declaringType.FullNameWithoutGenericArguments);
1238				sb.Append('+');
1239			}
1240			
1241			// '`' might be missing in nested generic classes
1242			sb.Append(classProps.Name);
1243			
1244			this.fullNameWithoutGenericArguments = sb.ToString();
1245			
1246			if (this.GetGenericArguments().Length > 0) {
1247				sb.Append("[");
1248				bool first = true;
1249				foreach(DebugType arg in this.GetGenericArguments()) {
1250					if (!first)
1251						sb.Append(",");
1252					first = false;
1253					sb.Append(arg.FullName);
1254				}
1255				sb.Append("]");
1256			}
1257			
1258			this.fullName = sb.ToString();
1259		}
1260		
1261		void LoadMembers()
1262		{
1263			System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
1264			
1265			if (corElementType == CorElementType.ARRAY || corElementType == CorElementType.SZARRAY) {
1266				// Arrays are special and normal loading does not work for them
1267				DebugType iList = DebugType.CreateFromName(this.AppDomain.Mscorlib, typeof(IList<>).FullName, null, new DebugType[] { (DebugType)this.GetElementType() });
1268				this.interfaces.Add(iList);
1269				this.interfaces.AddRange(iList.interfaces);
1270			} else {
1271				// Load interfaces
1272				foreach(InterfaceImplProps implProps in module.MetaData.EnumInterfaceImplProps((uint)this.MetadataToken)) {
1273					CorTokenType tkType = (CorTokenType)(implProps.Interface & 0xFF000000);
1274					if (tkType == CorTokenType.TypeDef || tkType == CorTokenType.TypeRef) {
1275						// TODO: Fix properly
1276						try {
1277							this.interfaces.Add(DebugType.CreateFromTypeDefOrRef(module, false, implProps.Interface, null));
1278						} catch (DebuggerException) {
1279						}
1280					} else if (tkType == CorTokenType.TypeSpec) {
1281						this.interfaces.Add(DebugType.CreateFromTypeSpec(module, implProps.Interface, this));
1282					} else {
1283						throw new DebuggerException("Uknown token type for interface: " + tkType);
1284					}
1285				}
1286				
1287				// Load fields
1288				foreach(FieldProps field in module.MetaData.EnumFieldProps((uint)this.MetadataToken)) {
1289					DebugFieldInfo fieldInfo = new DebugFieldInfo(this, field);
1290					AddMember(fieldInfo);
1291				};
1292				
1293				// Load methods
1294				foreach(MethodProps m in module.MetaData.EnumMethodProps((uint)this.MetadataToken)) {
1295					AddMember(new DebugMethodInfo(this, m));
1296				}
1297				
1298				// Load properties
1299				foreach(PropertyProps prop in module.MetaData.EnumPropertyProps((uint)this.MetadataToken)) {
1300					DebugPropertyInfo propInfo = new DebugPropertyInfo(
1301						this,
1302						prop.Name,
1303						prop.GetterMethod != 0x06000000 ? GetMethod(prop.GetterMethod) : null,
1304						prop.SetterMethod != 0x06000000 ? GetMethod(prop.SetterMethod) : null
1305					);
1306					if (propInfo.GetGetMethod() != null)
1307						((DebugMethodInfo)propInfo.GetGetMethod()).IsPropertyAccessor = true;
1308					if (propInfo.GetSetMethod() != null)
1309						((DebugMethodInfo)propInfo.GetSetMethod()).IsPropertyAccessor = true;
1310					AddMember(propInfo);
1311				}
1312			}
1313			
1314			if (this.Process.Options.Verbose)
1315				this.Process.TraceMessage("Loaded {0} ({1} ms)", this.FullName, stopwatch.ElapsedMilliseconds);
1316			
1317			// Load base type
1318			Type baseType = this.BaseType;
1319			
1320			// Add base type's inerfaces
1321			if (baseType != null) {
1322				foreach (DebugType debugType in baseType.GetInterfaces()) {
1323					if (!this.interfaces.Contains(debugType)) {
1324						this.interfaces.Add(debugType);
1325					}
1326				}
1327			}
1328		}
1329		
1330		void AddMember(MemberInfo member)
1331		{
1332			if (!membersByName.ContainsKey(member.Name))
1333				membersByName.Add(member.Name, new List<MemberInfo>(1));
1334			membersByName[member.Name].Add(member);
1335			membersByToken[member.MetadataToken] = member;
1336		}
1337		
1338		public override bool Equals(object o)
1339		{
1340			DebugType other = o as DebugType;
1341			if (other == null)
1342				return false;
1343			return this.MetadataToken == other.MetadataToken && // Performance optimization
1344			       this.DebugModule == other.DebugModule &&
1345			       this.FullName == other.FullName;
1346		}
1347		
1348		public override int GetHashCode()
1349		{
1350			return this.FullName.GetHashCode();
1351		}
1352		
1353		public static bool operator == (DebugType a, DebugType b)
1354		{
1355			if ((object)a == (object)b)
1356				return true;
1357			if (((object)a == null) || ((object)b == null))
1358				return false;
1359			return a.Equals(b);
1360		}
1361		
1362		public static bool operator != (DebugType a, DebugType b)
1363		{
1364			return !(a == b);
1365		}
1366		
1367		/// <inheritdoc/>
1368		public override string ToString()
1369		{
1370			return this.FullName;
1371		}
1372		
1373		DebugType IDebugMemberInfo.MemberType {
1374			get { return null; }
1375		}
1376	}
1377}