2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System / Attribute.cs
blob333e0e39f775ce5d20572979344c75c7eed8ca0d
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)
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.
32 using System.Collections.Generic;
33 using System.Reflection;
34 using System.Runtime.InteropServices;
36 namespace System
38 [AttributeUsage (AttributeTargets.All)]
39 [Serializable]
40 [ComVisible (true)]
41 [ComDefaultInterface (typeof (_Attribute))]
42 [ClassInterfaceAttribute (ClassInterfaceType.None)]
43 public abstract class Attribute : _Attribute {
44 protected Attribute ()
48 public virtual object TypeId {
49 get {
50 // Derived classes should override this default behaviour as appropriate
51 return this.GetType ();
55 private static void CheckParameters (object element, Type attributeType)
57 // neither parameter is allowed to be null
58 if (element == null)
59 throw new ArgumentNullException ("element");
61 if (attributeType == null)
62 throw new ArgumentNullException ("attributeType");
64 if (!typeof (Attribute).IsAssignableFrom (attributeType))
65 throw new ArgumentException (Locale.GetText (
66 "Type is not derived from System.Attribute."), "attributeType");
69 private static Attribute FindAttribute (object[] attributes)
71 // if there exists more than one attribute of the given type, throw an exception
72 if (attributes.Length > 1) {
73 throw new AmbiguousMatchException (Locale.GetText (
74 "<element> has more than one attribute of type <attribute_type>"));
77 if (attributes.Length < 1)
78 return null;
80 // tested above for '> 1' and and '< 1', so only '== 1' is left,
81 // i.e. we found the attribute
82 return (Attribute) attributes[0];
85 public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType)
87 return GetCustomAttribute (element, attributeType, true);
90 public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType)
92 return GetCustomAttribute (element, attributeType, true);
95 public static Attribute GetCustomAttribute (Assembly element, Type attributeType)
97 return GetCustomAttribute (element, attributeType, true);
100 public static Attribute GetCustomAttribute (Module element, Type attributeType)
102 return GetCustomAttribute (element, attributeType, true);
105 public static Attribute GetCustomAttribute (Module element, Type attributeType, bool inherit)
107 // neither parameter is allowed to be null
108 CheckParameters (element, attributeType);
110 // Module inheritance hierarchies CAN NOT be searched for attributes, so the second
111 // parameter of GetCustomAttributes () is IGNORED.
112 object[] attributes = element.GetCustomAttributes (attributeType, inherit);
114 return FindAttribute (attributes);
117 public static Attribute GetCustomAttribute (Assembly element, Type attributeType, bool inherit)
119 // neither parameter is allowed to be null
120 CheckParameters (element, attributeType);
122 // Assembly inheritance hierarchies CAN NOT be searched for attributes, so the second
123 // parameter of GetCustomAttributes () is IGNORED.
124 object[] attributes = element.GetCustomAttributes (attributeType, inherit);
126 return FindAttribute (attributes);
129 public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType, bool inherit)
131 // neither parameter is allowed to be null
132 CheckParameters (element, attributeType);
134 object[] attributes = GetCustomAttributes (element, attributeType, inherit);
136 return FindAttribute (attributes);
139 public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType, bool inherit)
141 // neither parameter is allowed to be null
142 CheckParameters (element, attributeType);
144 // MemberInfo inheritance hierarchies can be searched for attributes, so the second
145 // parameter of GetCustomAttribute () is respected.
146 return MonoCustomAttrs.GetCustomAttribute (element, attributeType, inherit);
149 public static Attribute[] GetCustomAttributes (Assembly element)
151 return GetCustomAttributes (element, true);
154 public static Attribute[] GetCustomAttributes (ParameterInfo element)
156 return GetCustomAttributes (element, true);
159 public static Attribute[] GetCustomAttributes (MemberInfo element)
161 return GetCustomAttributes (element, true);
164 public static Attribute[] GetCustomAttributes (Module element)
166 return GetCustomAttributes (element, true);
169 public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType)
171 return GetCustomAttributes (element, attributeType, true);
174 public static Attribute[] GetCustomAttributes (Module element, Type attributeType)
176 return GetCustomAttributes (element, attributeType, true);
179 public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType)
181 return GetCustomAttributes (element, attributeType, true);
184 public static Attribute[] GetCustomAttributes (MemberInfo element, Type type)
186 return GetCustomAttributes (element, type, true);
189 public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType, bool inherit)
191 // element parameter is not allowed to be null
192 CheckParameters (element, attributeType);
194 return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
197 public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType, bool inherit)
199 // element parameter is not allowed to be null
200 CheckParameters (element, attributeType);
202 Attribute [] attributes;
203 if (inherit && TryGetParamCustomAttributes (element, attributeType, out attributes))
204 return attributes;
206 return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
209 public static Attribute[] GetCustomAttributes (Module element, Type attributeType, bool inherit)
211 // element parameter is not allowed to be null
212 CheckParameters (element, attributeType);
214 return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
217 public static Attribute[] GetCustomAttributes (MemberInfo element, Type type, bool inherit)
219 // element parameter is not allowed to be null
220 CheckParameters (element, type);
222 // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider
223 // implementation, but not in the Attributes, so directly get the attributes
224 // from MonoCustomAttrs instead of going throught the PropertyInfo's
225 // ICustomAttributeProvider
226 MemberTypes mtype = element.MemberType;
227 if (mtype == MemberTypes.Property)
228 return (Attribute []) MonoCustomAttrs.GetCustomAttributes (element, type, inherit);
229 return (Attribute []) element.GetCustomAttributes (type, inherit);
232 public static Attribute[] GetCustomAttributes (Module element, bool inherit)
234 return GetCustomAttributes (element, typeof (Attribute), inherit);
237 public static Attribute[] GetCustomAttributes (Assembly element, bool inherit)
239 return GetCustomAttributes (element, typeof (Attribute), inherit);
242 public static Attribute[] GetCustomAttributes (MemberInfo element, bool inherit)
244 return GetCustomAttributes (element, typeof (Attribute), inherit);
247 public static Attribute[] GetCustomAttributes (ParameterInfo element, bool inherit)
249 // element parameter is not allowed to be null
250 CheckParameters (element, typeof (Attribute));
252 return GetCustomAttributes (element, typeof (Attribute), inherit);
255 public override int GetHashCode ()
257 return base.GetHashCode ();
260 public virtual bool IsDefaultAttribute ()
262 // Derived classes should override this default behaviour as appropriate
263 return false;
266 public static bool IsDefined (Module element, Type attributeType)
268 return IsDefined (element, attributeType, false);
271 public static bool IsDefined (ParameterInfo element, Type attributeType)
273 return IsDefined (element, attributeType, true);
276 public static bool IsDefined (MemberInfo element, Type attributeType)
278 return IsDefined (element, attributeType, true);
281 public static bool IsDefined (Assembly element, Type attributeType)
283 return IsDefined (element, attributeType, true);
286 public static bool IsDefined (MemberInfo element, Type attributeType, bool inherit)
288 CheckParameters (element, attributeType);
290 MemberTypes mtype = element.MemberType;
291 if (mtype != MemberTypes.Constructor && mtype != MemberTypes.Event &&
292 mtype != MemberTypes.Field && mtype != MemberTypes.Method &&
293 mtype != MemberTypes.Property && mtype != MemberTypes.TypeInfo &&
294 mtype != MemberTypes.NestedType)
295 throw new NotSupportedException (Locale.GetText (
296 "Element is not a constructor, method, property, event, type or field."));
297 // MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider
298 // implementation, but not in the Attributes, so directly get the attributes
299 // from MonoCustomAttrs instead of going throught the PropertyInfo's
300 // ICustomAttributeProvider
301 if (mtype == MemberTypes.Property)
302 return MonoCustomAttrs.IsDefined (element, attributeType, inherit);
303 return ((MemberInfo) element).IsDefined (attributeType, inherit);
306 public static bool IsDefined (Assembly element, Type attributeType, bool inherit)
308 CheckParameters (element, attributeType);
310 return element.IsDefined (attributeType, inherit);
313 public static bool IsDefined (Module element, Type attributeType, bool inherit)
315 CheckParameters (element, attributeType);
317 return element.IsDefined (attributeType, inherit);
320 public static bool IsDefined (ParameterInfo element, Type attributeType, bool inherit)
322 CheckParameters (element, attributeType);
324 if (element.IsDefined (attributeType, inherit))
325 return true;
327 if (inherit)
328 return IsDefinedOnParameter (element, attributeType);
330 return false;
333 static bool IsDefinedOnParameter (ParameterInfo parameter, Type attributeType)
335 var member = parameter.Member;
336 if (member.MemberType != MemberTypes.Method)
337 return false;
339 var method = ((MethodInfo) member).GetBaseMethod ();
341 while (true) {
342 var param = method.GetParameters () [parameter.Position];
343 if (param.IsDefined (attributeType, false))
344 return true;
346 var base_method = method.GetBaseMethod ();
347 if (base_method == method)
348 break;
350 method = base_method;
353 return false;
356 static bool TryGetParamCustomAttributes (ParameterInfo parameter, Type attributeType, out Attribute [] attributes)
358 attributes = null;
360 if (parameter.Member.MemberType != MemberTypes.Method)
361 return false;
363 var method = (MethodInfo) parameter.Member;
364 var definition = method.GetBaseDefinition ();
366 if (method == definition)
367 return false;
369 var types = new List<Type> ();
370 var custom_attributes = new List<Attribute> ();
372 while (true) {
373 var param = method.GetParameters () [parameter.Position];
374 var param_attributes = (Attribute []) param.GetCustomAttributes (attributeType, false);
375 foreach (var param_attribute in param_attributes) {
376 var param_type = param_attribute.GetType ();
377 if (types.Contains (param_type))
378 continue;
380 types.Add (param_type);
381 custom_attributes.Add (param_attribute);
384 var base_method = method.GetBaseMethod ();
385 if (base_method == method)
386 break;
388 method = base_method;
391 attributes = (Attribute []) Array.CreateInstance (attributeType, custom_attributes.Count);
392 custom_attributes.CopyTo (attributes, 0);
394 return true;
397 public virtual bool Match (object obj)
399 // default action is the same as Equals.
400 // Derived classes should override as appropriate
401 return this.Equals (obj);
404 public override bool Equals (object obj)
406 if (obj == null || !(obj is Attribute))
407 return false;
410 // This is needed because Attribute.Equals does a deep
411 // compare. Ran into this with vbnc
413 return ValueType.DefaultEquals (this, obj);
416 void _Attribute.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
418 throw new NotImplementedException ();
421 void _Attribute.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
423 throw new NotImplementedException ();
426 void _Attribute.GetTypeInfoCount (out uint pcTInfo)
428 throw new NotImplementedException ();
431 void _Attribute.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
432 IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
434 throw new NotImplementedException ();