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