Fri Sep 27 15:06:29 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System / MonoCustomAttrs.cs
1 // System.MonoCustomAttrs.cs
2 // Hooks into the runtime to get custom attributes for reflection handles
3 //
4 // Paolo Molaro (lupus@ximian.com)
5 //
6 // (c) 2002 Ximian, Inc.
7
8 using System;
9 using System.Reflection;
10 using System.Collections;
11 using System.Runtime.CompilerServices;
12
13 namespace System {
14         internal class MonoCustomAttrs {
15
16                 static Hashtable handle_to_attrs = new Hashtable ();
17
18                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
19                 internal static extern object[] GetCustomAttributes (ICustomAttributeProvider obj);
20
21                 private static object[] from_cache (ICustomAttributeProvider obj) {
22                         object[] res = (object[])handle_to_attrs [obj];
23                         if (res != null)
24                                 return res;
25                         res = GetCustomAttributes (obj);
26                         handle_to_attrs.Add (obj, res);
27                         return res;
28                 }
29
30                 internal static object[] GetCustomAttributes (ICustomAttributeProvider obj, Type attributeType, bool inherit) {
31                         object[] res = from_cache (obj);
32                         // shortcut
33                         if (res.Length == 1 && (res[0].GetType () == attributeType || res[0].GetType().IsSubclassOf(attributeType)))
34                                 return (object[])res.Clone ();
35                         ArrayList a = new ArrayList ();
36                         Type btype = obj as Type;
37                         do {
38                                 foreach (object attr in res) {
39                                         if (attributeType.Equals (attr.GetType ()) || attr.GetType().IsSubclassOf(attributeType))
40                                                 a.Add (attr);
41                                 }
42                                 if (btype != null && ((btype = btype.BaseType) != null)) {
43                                         res = from_cache (btype);
44                                 } else {
45                                         break;
46                                 }
47                         } while (inherit && btype != null && ((btype = btype.BaseType) != null));
48                         Attribute[] r = new Attribute [a.Count];
49                         a.CopyTo (r);
50                         return r;
51                 }
52
53                 internal static object[] GetCustomAttributes (ICustomAttributeProvider obj, bool inherit) {
54                         Type btype = obj as Type;
55                         if (!inherit || btype == null) {
56                                 return (Object[])from_cache (obj).Clone ();
57                         } else {
58                                 ArrayList a = new ArrayList ();
59                                 a.AddRange (from_cache (obj));
60                                 while ((btype = btype.BaseType) != null) {
61                                         a.AddRange (from_cache (btype));
62                                 }
63                                 Attribute[] r = new Attribute [a.Count];
64                                 a.CopyTo (r);
65                                 return (object[])r;
66                         }
67                 }
68                 internal static bool IsDefined (ICustomAttributeProvider obj, Type attributeType, bool inherit) {
69                         object[] res = from_cache (obj);
70                         foreach (object attr in res) {
71                                 if (attributeType.Equals (attr.GetType ()))
72                                         return true;
73                         }
74                         Type btype = obj as Type;
75                         if (inherit && (btype != null) && ((btype = btype.BaseType) != null))
76                                 return IsDefined (btype, attributeType, inherit);
77                         return false;
78                 }
79         }
80 }