1 // 2 // TypeReference.cs 3 // 4 // Author: 5 // Jb Evain (jbevain@gmail.com) 6 // 7 // Copyright (c) 2008 - 2011 Jb Evain 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 29 using System; 30 31 using Mono.Cecil.Metadata; 32 using Mono.Collections.Generic; 33 34 namespace Mono.Cecil { 35 36 public enum MetadataType : byte { 37 Void = ElementType.Void, 38 Boolean = ElementType.Boolean, 39 Char = ElementType.Char, 40 SByte = ElementType.I1, 41 Byte = ElementType.U1, 42 Int16 = ElementType.I2, 43 UInt16 = ElementType.U2, 44 Int32 = ElementType.I4, 45 UInt32 = ElementType.U4, 46 Int64 = ElementType.I8, 47 UInt64 = ElementType.U8, 48 Single = ElementType.R4, 49 Double = ElementType.R8, 50 String = ElementType.String, 51 Pointer = ElementType.Ptr, 52 ByReference = ElementType.ByRef, 53 ValueType = ElementType.ValueType, 54 Class = ElementType.Class, 55 Var = ElementType.Var, 56 Array = ElementType.Array, 57 GenericInstance = ElementType.GenericInst, 58 TypedByReference = ElementType.TypedByRef, 59 IntPtr = ElementType.I, 60 UIntPtr = ElementType.U, 61 FunctionPointer = ElementType.FnPtr, 62 Object = ElementType.Object, 63 MVar = ElementType.MVar, 64 RequiredModifier = ElementType.CModReqD, 65 OptionalModifier = ElementType.CModOpt, 66 Sentinel = ElementType.Sentinel, 67 Pinned = ElementType.Pinned, 68 } 69 70 public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext { 71 72 string @namespace; 73 bool value_type; 74 internal IMetadataScope scope; 75 internal ModuleDefinition module; 76 77 internal ElementType etype = ElementType.None; 78 79 string fullname; 80 81 protected Collection<GenericParameter> generic_parameters; 82 83 public override string Name { 84 get { return base.Name; } 85 set { 86 base.Name = value; 87 fullname = null; 88 } 89 } 90 91 public virtual string Namespace { 92 get { return @namespace; } 93 set { 94 @namespace = value; 95 fullname = null; 96 } 97 } 98 99 public virtual bool IsValueType { 100 get { return value_type; } 101 set { value_type = value; } 102 } 103 104 public override ModuleDefinition Module { 105 get { 106 if (module != null) 107 return module; 108 109 var declaring_type = this.DeclaringType; 110 if (declaring_type != null) 111 return declaring_type.Module; 112 113 return null; 114 } 115 } 116 117 IGenericParameterProvider IGenericContext.Type { 118 get { return this; } 119 } 120 121 IGenericParameterProvider IGenericContext.Method { 122 get { return null; } 123 } 124 125 GenericParameterType IGenericParameterProvider.GenericParameterType { 126 get { return GenericParameterType.Type; } 127 } 128 129 public virtual bool HasGenericParameters { 130 get { return !generic_parameters.IsNullOrEmpty (); } 131 } 132 133 public virtual Collection<GenericParameter> GenericParameters { 134 get { 135 if (generic_parameters != null) 136 return generic_parameters; 137 138 return generic_parameters = new GenericParameterCollection (this); 139 } 140 } 141 142 public virtual IMetadataScope Scope { 143 get { 144 var declaring_type = this.DeclaringType; 145 if (declaring_type != null) 146 return declaring_type.Scope; 147 148 return scope; 149 } 150 set { 151 var declaring_type = this.DeclaringType; 152 if (declaring_type != null) { 153 declaring_type.Scope = value; 154 return; 155 } 156 157 scope = value; 158 } 159 } 160 161 public bool IsNested { 162 get { return this.DeclaringType != null; } 163 } 164 165 public override TypeReference DeclaringType { 166 get { return base.DeclaringType; } 167 set { 168 base.DeclaringType = value; 169 fullname = null; 170 } 171 } 172 173 public override string FullName { 174 get { 175 if (fullname != null) 176 return fullname; 177 178 if (IsNested) 179 return fullname = DeclaringType.FullName + "/" + Name; 180 181 if (string.IsNullOrEmpty (@namespace)) 182 return fullname = Name; 183 184 return fullname = @namespace + "." + Name; 185 } 186 } 187 188 public virtual bool IsByReference { 189 get { return false; } 190 } 191 192 public virtual bool IsPointer { 193 get { return false; } 194 } 195 196 public virtual bool IsSentinel { 197 get { return false; } 198 } 199 200 public virtual bool IsArray { 201 get { return false; } 202 } 203 204 public virtual bool IsGenericParameter { 205 get { return false; } 206 } 207 208 public virtual bool IsGenericInstance { 209 get { return false; } 210 } 211 212 public virtual bool IsRequiredModifier { 213 get { return false; } 214 } 215 216 public virtual bool IsOptionalModifier { 217 get { return false; } 218 } 219 220 public virtual bool IsPinned { 221 get { return false; } 222 } 223 224 public virtual bool IsFunctionPointer { 225 get { return false; } 226 } 227 228 public virtual bool IsPrimitive { 229 get { return etype.IsPrimitive (); } 230 } 231 232 public virtual MetadataType MetadataType { 233 get { 234 switch (etype) { 235 case ElementType.None: 236 return IsValueType ? MetadataType.ValueType : MetadataType.Class; 237 default: 238 return (MetadataType) etype; 239 } 240 } 241 } 242 TypeReference(string @namespace, string name)243 protected TypeReference (string @namespace, string name) 244 : base (name) 245 { 246 this.@namespace = @namespace ?? string.Empty; 247 this.token = new MetadataToken (TokenType.TypeRef, 0); 248 } 249 TypeReference(string @namespace, string name, ModuleDefinition module, IMetadataScope scope)250 public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) 251 : this (@namespace, name) 252 { 253 this.module = module; 254 this.scope = scope; 255 } 256 TypeReference(string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType)257 public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) : 258 this (@namespace, name, module, scope) 259 { 260 value_type = valueType; 261 } 262 GetElementType()263 public virtual TypeReference GetElementType () 264 { 265 return this; 266 } 267 Resolve()268 public virtual TypeDefinition Resolve () 269 { 270 var module = this.Module; 271 if (module == null) 272 throw new NotSupportedException (); 273 274 return module.Resolve (this); 275 } 276 } 277 278 static partial class Mixin { 279 IsPrimitive(this ElementType self)280 public static bool IsPrimitive (this ElementType self) 281 { 282 switch (self) { 283 case ElementType.Boolean: 284 case ElementType.Char: 285 case ElementType.I: 286 case ElementType.U: 287 case ElementType.I1: 288 case ElementType.U1: 289 case ElementType.I2: 290 case ElementType.U2: 291 case ElementType.I4: 292 case ElementType.U4: 293 case ElementType.I8: 294 case ElementType.U8: 295 case ElementType.R4: 296 case ElementType.R8: 297 return true; 298 default: 299 return false; 300 } 301 } 302 IsTypeOf(this TypeReference self, string @namespace, string name)303 public static bool IsTypeOf (this TypeReference self, string @namespace, string name) 304 { 305 return self.Name == name 306 && self.Namespace == @namespace; 307 } 308 IsTypeSpecification(this TypeReference type)309 public static bool IsTypeSpecification (this TypeReference type) 310 { 311 switch (type.etype) { 312 case ElementType.Array: 313 case ElementType.ByRef: 314 case ElementType.CModOpt: 315 case ElementType.CModReqD: 316 case ElementType.FnPtr: 317 case ElementType.GenericInst: 318 case ElementType.MVar: 319 case ElementType.Pinned: 320 case ElementType.Ptr: 321 case ElementType.SzArray: 322 case ElementType.Sentinel: 323 case ElementType.Var: 324 return true; 325 } 326 327 return false; 328 } 329 CheckedResolve(this TypeReference self)330 public static TypeDefinition CheckedResolve (this TypeReference self) 331 { 332 var type = self.Resolve (); 333 if (type == null) 334 throw new ResolutionException (self); 335 336 return type; 337 } 338 } 339 } 340