1 // System.MonoCustomAttrs.cs
2 // Hooks into the runtime to get custom attributes for reflection handles
5 // Paolo Molaro (lupus@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
12 using System.Reflection;
13 using System.Collections;
14 using System.Runtime.CompilerServices;
17 internal class MonoCustomAttrs {
19 static Hashtable handle_to_attrs = new Hashtable ();
21 [MethodImplAttribute(MethodImplOptions.InternalCall)]
22 internal static extern object[] GetCustomAttributes (ICustomAttributeProvider obj);
24 private static object[] from_cache (ICustomAttributeProvider obj)
26 object[] res = (object []) handle_to_attrs [obj];
29 res = GetCustomAttributes (obj);
30 handle_to_attrs.Add (obj, res);
34 internal static Attribute GetCustomAttribute (ICustomAttributeProvider obj,
39 throw new ArgumentNullException ("attribute_type"); // argument name in the caller
41 object[] res = from_cache (obj);
42 ICustomAttributeProvider btype = obj;
43 Attribute result = null;
46 foreach (object attr in res) {
47 if (!attributeType.IsAssignableFrom (attr.GetType ()))
51 string msg = "'{0}' has more than one attribute of type '{1}";
52 msg = String.Format (msg, obj, attributeType);
53 throw new AmbiguousMatchException (msg);
55 result = (Attribute) attr;
58 if (inherit && (btype = GetBase (btype)) != null)
59 res = from_cache (btype);
61 // Stop when encounters the first one for a given provider.
62 } while (inherit && result == null && btype != null);
67 internal static object[] GetCustomAttributes (ICustomAttributeProvider obj, Type attributeType, bool inherit)
70 return (object []) Array.CreateInstance (attributeType, 0);
73 object[] res = from_cache (obj);
75 if (!inherit && res.Length == 1) {
76 if (attributeType.IsAssignableFrom (res[0].GetType ())) {
77 r = (object []) Array.CreateInstance (attributeType, 1);
80 r = (object []) Array.CreateInstance (attributeType, 0);
85 ArrayList a = new ArrayList ();
86 ICustomAttributeProvider btype = obj;
88 foreach (object attr in res)
89 if (attributeType.IsAssignableFrom (attr.GetType ()))
92 if ((btype = GetBase (btype)) != null)
93 res = from_cache (btype);
94 } while (inherit && btype != null);
96 return (object []) a.ToArray (attributeType);
99 internal static object [] GetCustomAttributes (ICustomAttributeProvider obj, bool inherit)
102 return new object [0]; //FIXME: Should i throw an exception here?
105 return (object []) from_cache (obj).Clone ();
107 ArrayList a = new ArrayList ();
108 ICustomAttributeProvider btype = obj;
109 a.AddRange (from_cache (btype));
110 while ((btype = GetBase (btype)) != null)
111 a.AddRange (from_cache (btype));
113 return (object []) a.ToArray (typeof (Attribute));
116 internal static bool IsDefined (ICustomAttributeProvider obj, Type attributeType, bool inherit)
118 object[] res = from_cache (obj);
119 foreach (object attr in res) {
120 if (attributeType.Equals (attr.GetType ()))
124 ICustomAttributeProvider btype = GetBase (obj);
125 if (inherit && (btype != null))
126 return IsDefined (btype, attributeType, inherit);
131 // Handles Type, MonoProperty and MonoMethod.
132 // The runtime has also cases for MonoEvent, MonoField, Assembly and ParameterInfo,
133 // but for those we return null here.
134 static ICustomAttributeProvider GetBase (ICustomAttributeProvider obj)
140 return ((Type) obj).BaseType;
142 MethodInfo method = null;
143 if (obj is MonoProperty) {
144 MonoProperty prop = (MonoProperty) obj;
145 method = prop.GetGetMethod ();
147 method = prop.GetSetMethod ();
148 } else if (obj is MonoMethod) {
149 method = (MethodInfo) obj;
153 * ParameterInfo -> null
158 if (method == null || !method.IsVirtual)
161 MethodInfo baseMethod = method.GetBaseDefinition ();
162 if (baseMethod == method)