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)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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
;
38 [AttributeUsage (AttributeTargets
.All
)]
41 [ComDefaultInterface (typeof (_Attribute
))]
42 [ClassInterfaceAttribute (ClassInterfaceType
.None
)]
43 public abstract class Attribute
: _Attribute
{
44 protected Attribute ()
48 public virtual object TypeId
{
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
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)
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
))
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
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
))
328 return IsDefinedOnParameter (element
, attributeType
);
333 static bool IsDefinedOnParameter (ParameterInfo parameter
, Type attributeType
)
335 var member
= parameter
.Member
;
336 if (member
.MemberType
!= MemberTypes
.Method
)
339 var method
= ((MethodInfo
) member
).GetBaseMethod ();
342 var param
= method
.GetParameters () [parameter
.Position
];
343 if (param
.IsDefined (attributeType
, false))
346 var base_method
= method
.GetBaseMethod ();
347 if (base_method
== method
)
350 method
= base_method
;
356 static bool TryGetParamCustomAttributes (ParameterInfo parameter
, Type attributeType
, out Attribute
[] attributes
)
360 if (parameter
.Member
.MemberType
!= MemberTypes
.Method
)
363 var method
= (MethodInfo
) parameter
.Member
;
364 var definition
= method
.GetBaseDefinition ();
366 if (method
== definition
)
369 var types
= new List
<Type
> ();
370 var custom_attributes
= new List
<Attribute
> ();
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
))
380 types
.Add (param_type
);
381 custom_attributes
.Add (param_attribute
);
384 var base_method
= method
.GetBaseMethod ();
385 if (base_method
== method
)
388 method
= base_method
;
391 attributes
= (Attribute
[]) Array
.CreateInstance (attributeType
, custom_attributes
.Count
);
392 custom_attributes
.CopyTo (attributes
, 0);
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
))
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 ();