/Mono.Cecil/TypeReference.cs

http://github.com/jbevain/cecil · C# · 352 lines · 286 code · 57 blank · 9 comment · 39 complexity · a7757a898608f631371d84a6a5385137 MD5 · raw file

  1. //
  2. // Author:
  3. // Jb Evain (jbevain@gmail.com)
  4. //
  5. // Copyright (c) 2008 - 2015 Jb Evain
  6. // Copyright (c) 2008 - 2011 Novell, Inc.
  7. //
  8. // Licensed under the MIT/X11 license.
  9. //
  10. using System;
  11. using System.Threading;
  12. using Mono.Cecil.Metadata;
  13. using Mono.Collections.Generic;
  14. namespace Mono.Cecil {
  15. public enum MetadataType : byte {
  16. Void = ElementType.Void,
  17. Boolean = ElementType.Boolean,
  18. Char = ElementType.Char,
  19. SByte = ElementType.I1,
  20. Byte = ElementType.U1,
  21. Int16 = ElementType.I2,
  22. UInt16 = ElementType.U2,
  23. Int32 = ElementType.I4,
  24. UInt32 = ElementType.U4,
  25. Int64 = ElementType.I8,
  26. UInt64 = ElementType.U8,
  27. Single = ElementType.R4,
  28. Double = ElementType.R8,
  29. String = ElementType.String,
  30. Pointer = ElementType.Ptr,
  31. ByReference = ElementType.ByRef,
  32. ValueType = ElementType.ValueType,
  33. Class = ElementType.Class,
  34. Var = ElementType.Var,
  35. Array = ElementType.Array,
  36. GenericInstance = ElementType.GenericInst,
  37. TypedByReference = ElementType.TypedByRef,
  38. IntPtr = ElementType.I,
  39. UIntPtr = ElementType.U,
  40. FunctionPointer = ElementType.FnPtr,
  41. Object = ElementType.Object,
  42. MVar = ElementType.MVar,
  43. RequiredModifier = ElementType.CModReqD,
  44. OptionalModifier = ElementType.CModOpt,
  45. Sentinel = ElementType.Sentinel,
  46. Pinned = ElementType.Pinned,
  47. }
  48. public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext {
  49. string @namespace;
  50. bool value_type;
  51. internal IMetadataScope scope;
  52. internal ModuleDefinition module;
  53. internal ElementType etype = ElementType.None;
  54. string fullname;
  55. protected Collection<GenericParameter> generic_parameters;
  56. public override string Name {
  57. get { return base.Name; }
  58. set {
  59. if (IsWindowsRuntimeProjection && value != base.Name)
  60. throw new InvalidOperationException ("Projected type reference name can't be changed.");
  61. base.Name = value;
  62. ClearFullName ();
  63. }
  64. }
  65. public virtual string Namespace {
  66. get { return @namespace; }
  67. set {
  68. if (IsWindowsRuntimeProjection && value != @namespace)
  69. throw new InvalidOperationException ("Projected type reference namespace can't be changed.");
  70. @namespace = value;
  71. ClearFullName ();
  72. }
  73. }
  74. public virtual bool IsValueType {
  75. get { return value_type; }
  76. set { value_type = value; }
  77. }
  78. public override ModuleDefinition Module {
  79. get {
  80. if (module != null)
  81. return module;
  82. var declaring_type = this.DeclaringType;
  83. if (declaring_type != null)
  84. return declaring_type.Module;
  85. return null;
  86. }
  87. }
  88. internal new TypeReferenceProjection WindowsRuntimeProjection {
  89. get { return (TypeReferenceProjection) projection; }
  90. set { projection = value; }
  91. }
  92. IGenericParameterProvider IGenericContext.Type {
  93. get { return this; }
  94. }
  95. IGenericParameterProvider IGenericContext.Method {
  96. get { return null; }
  97. }
  98. GenericParameterType IGenericParameterProvider.GenericParameterType {
  99. get { return GenericParameterType.Type; }
  100. }
  101. public virtual bool HasGenericParameters {
  102. get { return !generic_parameters.IsNullOrEmpty (); }
  103. }
  104. public virtual Collection<GenericParameter> GenericParameters {
  105. get {
  106. if (generic_parameters == null)
  107. Interlocked.CompareExchange (ref generic_parameters, new GenericParameterCollection (this), null);
  108. return generic_parameters;
  109. }
  110. }
  111. public virtual IMetadataScope Scope {
  112. get {
  113. var declaring_type = this.DeclaringType;
  114. if (declaring_type != null)
  115. return declaring_type.Scope;
  116. return scope;
  117. }
  118. set {
  119. var declaring_type = this.DeclaringType;
  120. if (declaring_type != null) {
  121. if (IsWindowsRuntimeProjection && value != declaring_type.Scope)
  122. throw new InvalidOperationException ("Projected type scope can't be changed.");
  123. declaring_type.Scope = value;
  124. return;
  125. }
  126. if (IsWindowsRuntimeProjection && value != scope)
  127. throw new InvalidOperationException ("Projected type scope can't be changed.");
  128. scope = value;
  129. }
  130. }
  131. public bool IsNested {
  132. get { return this.DeclaringType != null; }
  133. }
  134. public override TypeReference DeclaringType {
  135. get { return base.DeclaringType; }
  136. set {
  137. if (IsWindowsRuntimeProjection && value != base.DeclaringType)
  138. throw new InvalidOperationException ("Projected type declaring type can't be changed.");
  139. base.DeclaringType = value;
  140. ClearFullName ();
  141. }
  142. }
  143. public override string FullName {
  144. get {
  145. if (fullname != null)
  146. return fullname;
  147. var new_fullname = this.TypeFullName ();
  148. if (IsNested)
  149. new_fullname = DeclaringType.FullName + "/" + new_fullname;
  150. Interlocked.CompareExchange (ref fullname, new_fullname, null);
  151. return fullname;
  152. }
  153. }
  154. public virtual bool IsByReference {
  155. get { return false; }
  156. }
  157. public virtual bool IsPointer {
  158. get { return false; }
  159. }
  160. public virtual bool IsSentinel {
  161. get { return false; }
  162. }
  163. public virtual bool IsArray {
  164. get { return false; }
  165. }
  166. public virtual bool IsGenericParameter {
  167. get { return false; }
  168. }
  169. public virtual bool IsGenericInstance {
  170. get { return false; }
  171. }
  172. public virtual bool IsRequiredModifier {
  173. get { return false; }
  174. }
  175. public virtual bool IsOptionalModifier {
  176. get { return false; }
  177. }
  178. public virtual bool IsPinned {
  179. get { return false; }
  180. }
  181. public virtual bool IsFunctionPointer {
  182. get { return false; }
  183. }
  184. public virtual bool IsPrimitive {
  185. get { return etype.IsPrimitive (); }
  186. }
  187. public virtual MetadataType MetadataType {
  188. get {
  189. switch (etype) {
  190. case ElementType.None:
  191. return IsValueType ? MetadataType.ValueType : MetadataType.Class;
  192. default:
  193. return (MetadataType) etype;
  194. }
  195. }
  196. }
  197. protected TypeReference (string @namespace, string name)
  198. : base (name)
  199. {
  200. this.@namespace = @namespace ?? string.Empty;
  201. this.token = new MetadataToken (TokenType.TypeRef, 0);
  202. }
  203. public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope)
  204. : this (@namespace, name)
  205. {
  206. this.module = module;
  207. this.scope = scope;
  208. }
  209. public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) :
  210. this (@namespace, name, module, scope)
  211. {
  212. value_type = valueType;
  213. }
  214. protected virtual void ClearFullName ()
  215. {
  216. this.fullname = null;
  217. }
  218. public virtual TypeReference GetElementType ()
  219. {
  220. return this;
  221. }
  222. protected override IMemberDefinition ResolveDefinition ()
  223. {
  224. return this.Resolve ();
  225. }
  226. public new virtual TypeDefinition Resolve ()
  227. {
  228. var module = this.Module;
  229. if (module == null)
  230. throw new NotSupportedException ();
  231. return module.Resolve (this);
  232. }
  233. }
  234. static partial class Mixin {
  235. public static bool IsPrimitive (this ElementType self)
  236. {
  237. switch (self) {
  238. case ElementType.Boolean:
  239. case ElementType.Char:
  240. case ElementType.I:
  241. case ElementType.U:
  242. case ElementType.I1:
  243. case ElementType.U1:
  244. case ElementType.I2:
  245. case ElementType.U2:
  246. case ElementType.I4:
  247. case ElementType.U4:
  248. case ElementType.I8:
  249. case ElementType.U8:
  250. case ElementType.R4:
  251. case ElementType.R8:
  252. return true;
  253. default:
  254. return false;
  255. }
  256. }
  257. public static string TypeFullName (this TypeReference self)
  258. {
  259. return string.IsNullOrEmpty (self.Namespace)
  260. ? self.Name
  261. : self.Namespace + '.' + self.Name;
  262. }
  263. public static bool IsTypeOf (this TypeReference self, string @namespace, string name)
  264. {
  265. return self.Name == name
  266. && self.Namespace == @namespace;
  267. }
  268. public static bool IsTypeSpecification (this TypeReference type)
  269. {
  270. switch (type.etype) {
  271. case ElementType.Array:
  272. case ElementType.ByRef:
  273. case ElementType.CModOpt:
  274. case ElementType.CModReqD:
  275. case ElementType.FnPtr:
  276. case ElementType.GenericInst:
  277. case ElementType.MVar:
  278. case ElementType.Pinned:
  279. case ElementType.Ptr:
  280. case ElementType.SzArray:
  281. case ElementType.Sentinel:
  282. case ElementType.Var:
  283. return true;
  284. }
  285. return false;
  286. }
  287. public static TypeDefinition CheckedResolve (this TypeReference self)
  288. {
  289. var type = self.Resolve ();
  290. if (type == null)
  291. throw new ResolutionException (self);
  292. return type;
  293. }
  294. }
  295. }