/Mono.Cecil/CustomAttribute.cs
C# | 220 lines | 164 code | 47 blank | 9 comment | 20 complexity | c8c8c827af50a1220fc6960f541f498c 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 11using System; 12using System.Diagnostics; 13using System.Threading; 14using Mono.Collections.Generic; 15 16namespace Mono.Cecil { 17 18 public struct CustomAttributeArgument { 19 20 readonly TypeReference type; 21 readonly object value; 22 23 public TypeReference Type { 24 get { return type; } 25 } 26 27 public object Value { 28 get { return value; } 29 } 30 31 public CustomAttributeArgument (TypeReference type, object value) 32 { 33 Mixin.CheckType (type); 34 this.type = type; 35 this.value = value; 36 } 37 } 38 39 public struct CustomAttributeNamedArgument { 40 41 readonly string name; 42 readonly CustomAttributeArgument argument; 43 44 public string Name { 45 get { return name; } 46 } 47 48 public CustomAttributeArgument Argument { 49 get { return argument; } 50 } 51 52 public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument) 53 { 54 Mixin.CheckName (name); 55 this.name = name; 56 this.argument = argument; 57 } 58 } 59 60 public interface ICustomAttribute { 61 62 TypeReference AttributeType { get; } 63 64 bool HasFields { get; } 65 bool HasProperties { get; } 66 bool HasConstructorArguments { get; } 67 Collection<CustomAttributeNamedArgument> Fields { get; } 68 Collection<CustomAttributeNamedArgument> Properties { get; } 69 Collection<CustomAttributeArgument> ConstructorArguments { get; } 70 } 71 72 [DebuggerDisplay ("{AttributeType}")] 73 public sealed class CustomAttribute : ICustomAttribute { 74 75 internal CustomAttributeValueProjection projection; 76 readonly internal uint signature; 77 internal bool resolved; 78 MethodReference constructor; 79 byte [] blob; 80 internal Collection<CustomAttributeArgument> arguments; 81 internal Collection<CustomAttributeNamedArgument> fields; 82 internal Collection<CustomAttributeNamedArgument> properties; 83 84 public MethodReference Constructor { 85 get { return constructor; } 86 set { constructor = value; } 87 } 88 89 public TypeReference AttributeType { 90 get { return constructor.DeclaringType; } 91 } 92 93 public bool IsResolved { 94 get { return resolved; } 95 } 96 97 public bool HasConstructorArguments { 98 get { 99 Resolve (); 100 101 return !arguments.IsNullOrEmpty (); 102 } 103 } 104 105 public Collection<CustomAttributeArgument> ConstructorArguments { 106 get { 107 Resolve (); 108 109 if (arguments == null) 110 Interlocked.CompareExchange (ref arguments, new Collection<CustomAttributeArgument> (), null); 111 112 return arguments; 113 } 114 } 115 116 public bool HasFields { 117 get { 118 Resolve (); 119 120 return !fields.IsNullOrEmpty (); 121 } 122 } 123 124 public Collection<CustomAttributeNamedArgument> Fields { 125 get { 126 Resolve (); 127 128 if (fields == null) 129 Interlocked.CompareExchange (ref fields, new Collection<CustomAttributeNamedArgument> (), null); 130 131 return fields; 132 } 133 } 134 135 public bool HasProperties { 136 get { 137 Resolve (); 138 139 return !properties.IsNullOrEmpty (); 140 } 141 } 142 143 public Collection<CustomAttributeNamedArgument> Properties { 144 get { 145 Resolve (); 146 147 if (properties == null) 148 Interlocked.CompareExchange (ref properties, new Collection<CustomAttributeNamedArgument> (), null); 149 150 return properties; 151 } 152 } 153 154 internal bool HasImage { 155 get { return constructor != null && constructor.HasImage; } 156 } 157 158 internal ModuleDefinition Module { 159 get { return constructor.Module; } 160 } 161 162 internal CustomAttribute (uint signature, MethodReference constructor) 163 { 164 this.signature = signature; 165 this.constructor = constructor; 166 this.resolved = false; 167 } 168 169 public CustomAttribute (MethodReference constructor) 170 { 171 this.constructor = constructor; 172 this.resolved = true; 173 } 174 175 public CustomAttribute (MethodReference constructor, byte [] blob) 176 { 177 this.constructor = constructor; 178 this.resolved = false; 179 this.blob = blob; 180 } 181 182 public byte [] GetBlob () 183 { 184 if (blob != null) 185 return blob; 186 187 if (!HasImage) 188 throw new NotSupportedException (); 189 190 return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); 191 } 192 193 void Resolve () 194 { 195 if (resolved || !HasImage) 196 return; 197 198 lock (Module.SyncRoot) { 199 if (resolved) 200 return; 201 202 Module.Read (this, (attribute, reader) => { 203 try { 204 reader.ReadCustomAttributeSignature (attribute); 205 resolved = true; 206 } catch (ResolutionException) { 207 if (arguments != null) 208 arguments.Clear (); 209 if (fields != null) 210 fields.Clear (); 211 if (properties != null) 212 properties.Clear (); 213 214 resolved = false; 215 } 216 }); 217 } 218 } 219 } 220}