9205c8b3b793f1adb076676537eb656c10593bfb
[mono.git] / mcs / class / corlib / System / Attribute.cs
1 //
2 // System.Attribute.cs
3 //
4 // Authors:
5 //   Miguel de Icaza (miguel@ximian.com) - Original
6 //   Nick D. Drochak II (ndrochak@gol.com) - Implemented most of the guts
7 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //
9 // (C) 2002, 2003 Ximian, Inc.  http://www.ximian.com
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Reflection;
33 using System.Runtime.InteropServices;
34
35 namespace System
36 {
37         [AttributeUsage (AttributeTargets.All)]
38         [Serializable]
39
40 #if NET_2_0
41         [ComVisible (true)]
42         [ComDefaultInterface (typeof (_Attribute))]
43 #endif
44
45 #if NET_1_1
46         [ClassInterfaceAttribute (ClassInterfaceType.None)]
47         public abstract class Attribute : _Attribute {
48 #else
49         public abstract class Attribute {
50 #endif
51                 protected Attribute ()
52                 {
53                 }
54
55                 public virtual object TypeId {
56                         get {
57                                 // Derived classes should override this default behaviour as appropriate
58                                 return this.GetType ();
59                         }
60                 }
61
62                 private static void CheckParameters (object element, Type attributeType)
63                 {
64                         // neither parameter is allowed to be null
65                         if (element == null)
66                                 throw new ArgumentNullException ("element");
67
68                         if (attributeType == null)
69                                 throw new ArgumentNullException ("attributeType");
70
71                         if (!typeof (Attribute).IsAssignableFrom (attributeType))
72                                 throw new ArgumentException (Locale.GetText (
73                                         "Type is not derived from System.Attribute."), "attributeType");
74                 }
75
76                 private static Attribute FindAttribute (object[] attributes)
77                 {
78                         // if there exists more than one attribute of the given type, throw an exception
79                         if (attributes.Length > 1) {
80                                 throw new AmbiguousMatchException (Locale.GetText (
81                                         "<element> has more than one attribute of type <attribute_type>"));
82                         }
83
84                         if (attributes.Length < 1)
85                                 return null;
86
87                         // tested above for '> 1' and and '< 1', so only '== 1' is left,
88                         // i.e. we found the attribute
89                         return (Attribute) attributes[0];
90                 }
91
92                 public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType)
93                 {
94                         return GetCustomAttribute (element, attributeType, true);
95                 }
96
97                 public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType)
98                 {
99                         return GetCustomAttribute (element, attributeType, true);
100                 }
101
102                 public static Attribute GetCustomAttribute (Assembly element, Type attributeType)
103                 {
104                         return GetCustomAttribute (element, attributeType, true);
105                 }
106
107                 public static Attribute GetCustomAttribute (Module element, Type attributeType)
108                 {
109                         return GetCustomAttribute (element, attributeType, true);
110                 }
111
112                 public static Attribute GetCustomAttribute (Module element, Type attributeType, bool inherit)
113                 {
114                         // neither parameter is allowed to be null
115                         CheckParameters (element, attributeType);
116
117                         // Module inheritance hierarchies CAN NOT be searched for attributes, so the second
118                         // parameter of GetCustomAttributes () is IGNORED.
119                         object[] attributes = element.GetCustomAttributes (attributeType, inherit);
120
121                         return FindAttribute (attributes);
122                 }
123
124                 public static Attribute GetCustomAttribute (Assembly element, Type attributeType, bool inherit)
125                 {
126                         // neither parameter is allowed to be null
127                         CheckParameters (element, attributeType);
128
129                         // Assembly inheritance hierarchies CAN NOT be searched for attributes, so the second
130                         // parameter of GetCustomAttributes () is IGNORED.
131                         object[] attributes = element.GetCustomAttributes (attributeType, inherit);
132
133                         return FindAttribute (attributes);
134                 }
135
136                 public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType, bool inherit)
137                 {
138                         // neither parameter is allowed to be null
139                         CheckParameters (element, attributeType);
140
141                         // ParameterInfo inheritance hierarchies CAN NOT be searched for attributes, so the second
142                         // parameter of GetCustomAttributes () is IGNORED.
143                         object[] attributes = element.GetCustomAttributes (attributeType, inherit);
144
145                         return FindAttribute (attributes);
146                 }
147
148                 public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType, bool inherit)
149                 {
150                         // neither parameter is allowed to be null
151                         CheckParameters (element, attributeType);
152
153                         // MemberInfo inheritance hierarchies can be searched for attributes, so the second
154                         // parameter of GetCustomAttribute () is respected.
155                         return MonoCustomAttrs.GetCustomAttribute (element, attributeType, inherit);
156                 }
157
158                 public static Attribute[] GetCustomAttributes (Assembly element)
159                 {
160                         return GetCustomAttributes (element, true);
161                 }
162
163                 public static Attribute[] GetCustomAttributes (ParameterInfo element)
164                 {
165                         return GetCustomAttributes (element, true);
166                 }
167
168                 public static Attribute[] GetCustomAttributes (MemberInfo element)
169                 {
170                         return GetCustomAttributes (element, true);
171                 }
172
173                 public static Attribute[] GetCustomAttributes (Module element)
174                 {
175                         return GetCustomAttributes (element, true);
176                 }
177
178                 public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType)
179                 {
180                         return GetCustomAttributes (element, attributeType, true);
181                 }
182
183                 public static Attribute[] GetCustomAttributes (Module element, Type attributeType)
184                 {
185                         return GetCustomAttributes (element, attributeType, true);
186                 }
187
188                 public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType)
189                 {
190                         return GetCustomAttributes (element, attributeType, true);
191                 }
192
193                 public static Attribute[] GetCustomAttributes (MemberInfo element, Type type)
194                 {
195                         return GetCustomAttributes (element, type, true);
196                 }
197
198                 public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType, bool inherit)
199                 {
200                         // element parameter is not allowed to be null
201                         CheckParameters (element, attributeType);
202
203                         return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
204                 }
205
206                 public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType, bool inherit)
207                 {
208                         // element parameter is not allowed to be null
209                         CheckParameters (element, attributeType);
210
211                         return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
212                 }
213
214                 public static Attribute[] GetCustomAttributes (Module element, Type attributeType, bool inherit)
215                 {
216                         // element parameter is not allowed to be null
217                         CheckParameters (element, attributeType);
218
219                         return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
220                 }
221
222                 public static Attribute[] GetCustomAttributes (MemberInfo element, Type type, bool inherit)
223                 {
224                         // element parameter is not allowed to be null
225                         CheckParameters (element, type);
226
227                         // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider 
228                         // implementation, but not in the Attributes, so directly get the attributes
229                         // from MonoCustomAttrs instead of going throught the PropertyInfo's 
230                         // ICustomAttributeProvider
231                         MemberTypes mtype = element.MemberType;
232                         if (mtype == MemberTypes.Property)
233                                 return (Attribute []) MonoCustomAttrs.GetCustomAttributes (element, type, inherit);
234                         return (Attribute []) element.GetCustomAttributes (type, inherit);
235                 }
236
237                 public static Attribute[] GetCustomAttributes (Module element, bool inherit)
238                 {
239                         // element parameter is not allowed to be null
240                         CheckParameters (element, typeof (Attribute));
241
242                         return (Attribute []) element.GetCustomAttributes (inherit);
243                 }
244
245                 public static Attribute[] GetCustomAttributes (Assembly element, bool inherit)
246                 {
247                         // element parameter is not allowed to be null
248                         CheckParameters (element, typeof (Attribute));
249
250                         return (Attribute []) element.GetCustomAttributes (inherit);
251                 }
252
253                 public static Attribute[] GetCustomAttributes (MemberInfo element, bool inherit)
254                 {
255                         // element parameter is not allowed to be null
256                         CheckParameters (element, typeof (Attribute));
257
258                         // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider 
259                         // implementation, but not in the Attributes, so directly get the attributes
260                         // from MonoCustomAttrs instead of going throught the PropertyInfo's 
261                         // ICustomAttributeProvider
262                         MemberTypes mtype = element.MemberType;
263                         if (mtype == MemberTypes.Property)
264                                 return (Attribute []) MonoCustomAttrs.GetCustomAttributes (element, inherit);
265                         return (Attribute []) element.GetCustomAttributes (inherit);
266                 }
267
268                 public static Attribute[] GetCustomAttributes (ParameterInfo element, bool inherit)
269                 {
270                         // element parameter is not allowed to be null
271                         CheckParameters (element, typeof (Attribute));
272
273                         return (Attribute []) element.GetCustomAttributes (inherit);
274                 }
275
276                 public override int GetHashCode ()
277                 {
278                         return base.GetHashCode ();
279                 }
280
281                 public virtual bool IsDefaultAttribute ()
282                 {
283                         // Derived classes should override this default behaviour as appropriate
284                         return false;
285                 }
286
287                 public static bool IsDefined (Module element, Type attributeType)
288                 {
289                         return IsDefined (element, attributeType, false);
290                 }
291
292                 public static bool IsDefined (ParameterInfo element, Type attributeType)
293                 {
294                         return IsDefined (element, attributeType, true);
295                 }
296
297                 public static bool IsDefined (MemberInfo element, Type attributeType)
298                 {
299                         return IsDefined (element, attributeType, true);
300                 }
301
302                 public static bool IsDefined (Assembly element, Type attributeType)
303                 {
304                         return IsDefined (element, attributeType, true);
305                 }
306
307                 public static bool IsDefined (MemberInfo element, Type attributeType, bool inherit)
308                 {
309                         CheckParameters (element, attributeType);
310
311                         MemberTypes mtype = element.MemberType;
312                         if (mtype != MemberTypes.Constructor && mtype != MemberTypes.Event &&
313                                 mtype != MemberTypes.Field       && mtype != MemberTypes.Method &&
314                                 mtype != MemberTypes.Property    && mtype != MemberTypes.TypeInfo &&
315                                 mtype != MemberTypes.NestedType)
316                                 throw new NotSupportedException (Locale.GetText (
317                                         "Element is not a constructor, method, property, event, type or field."));
318 #if NET_2_0
319                         // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider 
320                         // implementation, but not in the Attributes, so directly get the attributes
321                         // from MonoCustomAttrs instead of going throught the PropertyInfo's 
322                         // ICustomAttributeProvider
323                         if (mtype == MemberTypes.Property)
324                                 return MonoCustomAttrs.IsDefined (element, attributeType, inherit);
325 #endif
326                         return ((MemberInfo) element).IsDefined (attributeType, inherit);
327                 }
328
329                 public static bool IsDefined (Assembly element, Type attributeType, bool inherit)
330                 {
331                         CheckParameters (element, attributeType);
332
333                         return element.IsDefined (attributeType, inherit);
334                 }
335
336                 public static bool IsDefined (Module element, Type attributeType, bool inherit)
337                 {
338                         CheckParameters (element, attributeType);
339
340                         return element.IsDefined (attributeType, inherit);
341                 }
342
343                 // FIXME: MS apparently walks the inheritance way in some form.
344                 public static bool IsDefined (ParameterInfo element, Type attributeType, bool inherit)
345                 {
346                         CheckParameters (element, attributeType);
347
348                         if (element.IsDefined (attributeType, inherit))
349                                 return true;
350
351                         // FIXME: MS walks up the inheritance chain in some crazy way
352                         return IsDefined (element.Member, attributeType, inherit);
353                 }
354
355                 public virtual bool Match (object obj)
356                 {
357                         // default action is the same as Equals.
358                         // Derived classes should override as appropriate
359                         return this.Equals (obj);
360                 }
361
362                 public override bool Equals (object obj)
363                 {
364                         if (obj == null || !(obj is Attribute))
365                                 return false;
366
367                         //
368                         // This is needed because Attribute.Equals does a deep
369                         // compare.  Ran into this with vbnc
370                         //
371                         return ValueType.DefaultEquals (this, obj);
372                 }
373
374 #if NET_1_1
375                 void _Attribute.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
376                 {
377                         throw new NotImplementedException ();
378                 }
379
380                 void _Attribute.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
381                 {
382                         throw new NotImplementedException ();
383                 }
384
385                 void _Attribute.GetTypeInfoCount (out uint pcTInfo)
386                 {
387                         throw new NotImplementedException ();
388                 }
389
390                 void _Attribute.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
391                         IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
392                 {
393                         throw new NotImplementedException ();
394                 }
395 #endif
396         }
397 }