fc6888cb1708c5c60dfc3a5f1d7e53f06e09005f
[mono.git] / mcs / mcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 //
11
12 using System;
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
16
17 namespace Mono.CSharp {
18
19 public class TypeManager {
20         //
21         // A list of core types that the compiler requires or uses
22         //
23         static public Type object_type;
24         static public Type value_type;
25         static public Type string_type;
26         static public Type int32_type;
27         static public Type uint32_type;
28         static public Type int64_type;
29         static public Type uint64_type;
30         static public Type float_type;
31         static public Type double_type;
32         static public Type char_type;
33         static public Type short_type;
34         static public Type decimal_type;
35         static public Type bool_type;
36         static public Type sbyte_type;
37         static public Type byte_type;
38         static public Type ushort_type;
39         static public Type enum_type;
40         static public Type delegate_type;
41         static public Type multicast_delegate_type;
42         static public Type void_type;
43         static public Type enumeration_type;
44         static public Type array_type;
45         static public Type runtime_handle_type;
46         static public Type icloneable_type;
47         static public Type type_type;
48         static public Type ienumerator_type;
49         static public Type idisposable_type;
50         static public Type default_member_type;
51         static public Type iasyncresult_type;
52         static public Type asynccallback_type;
53         static public Type intptr_type;
54         static public Type monitor_type;
55         static public Type runtime_field_handle_type;
56         static public Type attribute_usage_type;
57         static public Type dllimport_type;
58         static public Type methodimpl_attr_type;
59         static public Type param_array_type;
60         static public Type void_ptr_type;
61         
62         //
63         // Internal, not really used outside
64         //
65         Type runtime_helpers_type;
66         
67         //
68         // These methods are called by code generated by the compiler
69         //
70         static public MethodInfo string_concat_string_string;
71         static public MethodInfo string_concat_object_object;
72         static public MethodInfo string_isinterneted_string;
73         static public MethodInfo system_type_get_type_from_handle;
74         static public MethodInfo object_getcurrent_void;
75         static public MethodInfo bool_movenext_void;
76         static public MethodInfo void_dispose_void;
77         static public MethodInfo void_monitor_enter_object;
78         static public MethodInfo void_monitor_exit_object;
79         static public MethodInfo void_initializearray_array_fieldhandle;
80         static public MethodInfo int_getlength_int;
81         static public MethodInfo delegate_combine_delegate_delegate;
82         static public MethodInfo delegate_remove_delegate_delegate;
83         
84         //
85         // The attribute constructors.
86         //
87         static public ConstructorInfo cons_param_array_attribute;
88         
89         // <remarks>
90         //   Holds the Array of Assemblies that have been loaded
91         //   (either because it is the default or the user used the
92         //   -r command line option)
93         // </remarks>
94         ArrayList assemblies;
95
96         // <remarks>
97         //  Keeps a list of module builders. We used this to do lookups
98         //  on the modulebuilder using GetType -- needed for arrays
99         // </remarks>
100         ArrayList modules;
101
102         // <remarks>
103         //   This is the type_cache from the assemblies to avoid
104         //   hitting System.Reflection on every lookup.
105         // </summary>
106         Hashtable types;
107
108         // <remarks>
109         //  This is used to hotld the corresponding TypeContainer objects
110         //  since we need this in FindMembers
111         // </remarks>
112         Hashtable typecontainers;
113
114         // <remarks>
115         //   Keeps track of those types that are defined by the
116         //   user's program
117         // </remarks>
118         ArrayList user_types;
119
120         // <remarks>
121         //   Keeps a mapping between TypeBuilders and their TypeContainers
122         // </remarks>
123         static PtrHashtable builder_to_container;
124
125         // <remarks>
126         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
127         //   the arguments to the method
128         // </remarks>
129         static Hashtable method_arguments;
130
131         // <remarks>
132         //   Maybe `method_arguments' should be replaced and only
133         //   method_internal_params should be kept?
134         // <remarks>
135         static Hashtable method_internal_params;
136
137         static PtrHashtable builder_to_interface;
138
139         // <remarks>
140         //  Keeps track of delegate types
141         // </remarks>
142
143         static Hashtable builder_to_delegate;
144
145         // <remarks>
146         //  Keeps track of enum types
147         // </remarks>
148
149         static Hashtable builder_to_enum;
150
151         // <remarks>
152         //  Keeps track of attribute types
153         // </remarks>
154
155         static Hashtable builder_to_attr;
156
157         public TypeManager ()
158         {
159                 assemblies = new ArrayList ();
160                 modules = new ArrayList ();
161                 user_types = new ArrayList ();
162                 types = new Hashtable ();
163                 typecontainers = new Hashtable ();
164                 builder_to_interface = new PtrHashtable ();
165                 builder_to_delegate = new PtrHashtable ();
166                 builder_to_enum  = new PtrHashtable ();
167                 builder_to_attr = new PtrHashtable ();
168         }
169
170         static TypeManager ()
171         {
172                 method_arguments = new PtrHashtable ();
173                 method_internal_params = new PtrHashtable ();
174                 builder_to_container = new PtrHashtable ();
175                 type_interface_cache = new PtrHashtable ();
176         }
177
178         public void AddUserType (string name, TypeBuilder t)
179         {
180                 types.Add (name, t);
181                 user_types.Add (t);
182         }
183         
184         public void AddUserType (string name, TypeBuilder t, TypeContainer tc)
185         {
186                 AddUserType (name, t);
187                 builder_to_container.Add (t, tc);
188                 typecontainers.Add (name, tc);
189         }
190
191         public void AddDelegateType (string name, TypeBuilder t, Delegate del)
192         {
193                 types.Add (name, t);
194                 builder_to_delegate.Add (t, del);
195         }
196         
197         public void AddEnumType (string name, TypeBuilder t, Enum en)
198         {
199                 types.Add (name, t);
200                 builder_to_enum.Add (t, en);
201         }
202
203         public void AddUserInterface (string name, TypeBuilder t, Interface i)
204         {
205                 AddUserType (name, t);
206                 builder_to_interface.Add (t, i);
207         }
208
209         public void RegisterAttrType (Type t, TypeContainer tc)
210         {
211                 builder_to_attr.Add (t, tc);
212         }
213                 
214         /// <summary>
215         ///   Returns the TypeContainer whose Type is `t' or null if there is no
216         ///   TypeContainer for `t' (ie, the Type comes from a library)
217         /// </summary>
218         public static TypeContainer LookupTypeContainer (Type t)
219         {
220                 return (TypeContainer) builder_to_container [t];
221         }
222
223         public Interface LookupInterface (Type t)
224         {
225                 return (Interface) builder_to_interface [t];
226         }
227
228         public static Delegate LookupDelegate (Type t)
229         {
230                 return (Delegate) builder_to_delegate [t];
231         }
232
233         public static Enum LookupEnum (Type t)
234         {
235                 return (Enum) builder_to_enum [t];
236         }
237         
238         public static TypeContainer LookupAttr (Type t)
239         {
240                 return (TypeContainer) builder_to_attr [t];
241         }
242         
243         /// <summary>
244         ///   Registers an assembly to load types from.
245         /// </summary>
246         public void AddAssembly (Assembly a)
247         {
248                 assemblies.Add (a);
249         }
250
251         /// <summary>
252         ///  Registers a module builder to lookup types from
253         /// </summary>
254         public void AddModule (ModuleBuilder mb)
255         {
256                 modules.Add (mb);
257         }
258
259         /// <summary>
260         ///   Returns the Type associated with @name
261         /// </summary>
262         public Type LookupType (string name)
263         {
264                 Type t;
265
266                 //
267                 // First lookup in user defined and cached values
268                 //
269
270                 t = (Type) types [name];
271                 if (t != null)
272                         return t;
273
274                 foreach (Assembly a in assemblies){
275                         t = a.GetType (name);
276                         if (t != null){
277                                 types [name] = t;
278
279                                 return t;
280                         }
281                 }
282
283                 foreach (ModuleBuilder mb in modules) {
284                         t = mb.GetType (name);
285                         if (t != null) {
286                                 types [name] = t;
287                                 return t;
288                         }
289                 }
290
291                 return null;
292         }
293
294         /// <summary>
295         ///   Returns the C# name of a type if possible, or the full type name otherwise
296         /// </summary>
297         static public string CSharpName (Type t)
298         {
299                 if (t == int32_type)
300                         return "int";
301                 else if (t == uint32_type)
302                         return "uint";
303                 else if (t == int64_type)
304                         return "long";
305                 else if (t == uint64_type)
306                         return "ulong";
307                 else if (t == float_type)
308                         return "float";
309                 else if (t == double_type)
310                         return "double";
311                 else if (t == char_type)
312                         return "char";
313                 else if (t == short_type)
314                         return "short";
315                 else if (t == decimal_type)
316                         return "decimal";
317                 else if (t == bool_type)
318                         return "bool";
319                 else if (t == sbyte_type)
320                         return "sbyte";
321                 else if (t == byte_type)
322                         return "byte";
323                 else if (t == short_type)
324                         return "short";
325                 else if (t == ushort_type)
326                         return "ushort";
327                 else if (t == string_type)
328                         return "string";
329                 else if (t == object_type)
330                         return "object";
331                 else if (t == void_type)
332                         return "void";
333                 else
334                         return t.FullName;
335         }
336
337         /// <summary>
338         ///   Looks up a type, and aborts if it is not found.  This is used
339         ///   by types required by the compiler
340         /// </summary>
341         Type CoreLookupType (string name)
342         {
343                 Type t = LookupType (name);
344
345                 if (t == null){
346                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
347                         Environment.Exit (0);
348                 }
349
350                 return t;
351         }
352
353         /// <summary>
354         ///   Returns the MethodInfo for a method named `name' defined
355         ///   in type `t' which takes arguments of types `args'
356         /// </summary>
357         MethodInfo GetMethod (Type t, string name, Type [] args)
358         {
359                 MethodInfo mi = t.GetMethod (name, args);
360
361                 if (mi == null)
362                         throw new Exception ("Can not find the core function `" + name + "'");
363
364                 return mi;
365         }
366
367         ConstructorInfo GetConstructor (Type t, Type [] args)
368         {
369                 ConstructorInfo ci = t.GetConstructor (args);
370
371                 if (ci == null)
372                         throw new Exception ("Can not find the core constructor for `" + t.FullName + "'");
373
374                 return ci;
375         }
376         
377         /// <remarks>
378         ///   The types have to be initialized after the initial
379         ///   population of the type has happened (for example, to
380         ///   bootstrap the corlib.dll
381         /// </remarks>
382         public void InitCoreTypes ()
383         {
384                 object_type   = CoreLookupType ("System.Object");
385                 value_type    = CoreLookupType ("System.ValueType");
386                 string_type   = CoreLookupType ("System.String");
387                 int32_type    = CoreLookupType ("System.Int32");
388                 int64_type    = CoreLookupType ("System.Int64");
389                 uint32_type   = CoreLookupType ("System.UInt32"); 
390                 uint64_type   = CoreLookupType ("System.UInt64"); 
391                 float_type    = CoreLookupType ("System.Single");
392                 double_type   = CoreLookupType ("System.Double");
393                 byte_type     = CoreLookupType ("System.Byte");
394                 sbyte_type    = CoreLookupType ("System.SByte");
395                 char_type     = CoreLookupType ("System.Char");
396                 short_type    = CoreLookupType ("System.Int16");
397                 ushort_type   = CoreLookupType ("System.UInt16");
398                 decimal_type  = CoreLookupType ("System.Decimal");
399                 bool_type     = CoreLookupType ("System.Boolean");
400                 enum_type     = CoreLookupType ("System.Enum");
401
402                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
403                 delegate_type           = CoreLookupType ("System.Delegate");
404
405                 array_type    = CoreLookupType ("System.Array");
406                 void_type     = CoreLookupType ("System.Void");
407                 type_type     = CoreLookupType ("System.Type");
408
409                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
410                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
411                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
412                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
413                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
414                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
415                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
416                 idisposable_type     = CoreLookupType ("System.IDisposable");
417                 icloneable_type      = CoreLookupType ("System.ICloneable");
418                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
419                 intptr_type          = CoreLookupType ("System.IntPtr");
420
421                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
422                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
423                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
424                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
425
426                 void_ptr_type        = CoreLookupType ("System.Void*");
427                 
428                 //
429                 // Now load the default methods that we use.
430                 //
431                 Type [] string_string = { string_type, string_type };
432                 string_concat_string_string = GetMethod (
433                         string_type, "Concat", string_string);
434
435                 Type [] object_object = { object_type, object_type };
436                 string_concat_object_object = GetMethod (
437                         string_type, "Concat", object_object);
438
439                 Type [] string_ = { string_type };
440                 string_isinterneted_string = GetMethod (
441                         string_type, "IsInterned", string_);
442                 
443                 Type [] runtime_type_handle = { runtime_handle_type };
444                 system_type_get_type_from_handle = GetMethod (
445                         type_type, "GetTypeFromHandle", runtime_type_handle);
446
447                 Type [] delegate_delegate = { delegate_type, delegate_type };
448                 delegate_combine_delegate_delegate = GetMethod (
449                                 delegate_type, "Combine", delegate_delegate);
450
451                 delegate_remove_delegate_delegate = GetMethod (
452                                 delegate_type, "Remove", delegate_delegate);
453
454                 //
455                 // Void arguments
456                 //
457                 Type [] void_arg = {  };
458                 object_getcurrent_void = GetMethod (
459                         ienumerator_type, "get_Current", void_arg);
460                 bool_movenext_void = GetMethod (
461                         ienumerator_type, "MoveNext", void_arg);
462                 void_dispose_void = GetMethod (
463                         idisposable_type, "Dispose", void_arg);
464
465                 //
466                 // object arguments
467                 //
468                 Type [] object_arg = { object_type };
469                 void_monitor_enter_object = GetMethod (
470                         monitor_type, "Enter", object_arg);
471                 void_monitor_exit_object = GetMethod (
472                         monitor_type, "Exit", object_arg);
473
474                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
475                 
476                 void_initializearray_array_fieldhandle = GetMethod (
477                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
478
479                 //
480                 // Array functions
481                 //
482                 Type [] int_arg = { int32_type };
483                 int_getlength_int = GetMethod (
484                         array_type, "GetLength", int_arg);
485                 
486                 //
487                 // Attributes
488                 //
489                 cons_param_array_attribute = GetConstructor (
490                         param_array_type, void_arg);
491                 
492         }
493
494         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
495         
496         public MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
497                                           MemberFilter filter, object criteria)
498         {
499                 //
500                 // We have to take care of arrays specially, because GetType on
501                 // a TypeBuilder array will return a Type, not a TypeBuilder,
502                 // and we can not call FindMembers on this type.
503                 //
504                 if (t.IsSubclassOf (TypeManager.array_type))
505                         return TypeManager.array_type.FindMembers (mt, bf, filter, criteria);
506                 
507                 if (!(t is TypeBuilder)){
508                         //
509                         // Since FindMembers will not lookup both static and instance
510                         // members, we emulate this behaviour here.
511                         //
512                         if ((bf & instance_and_static) == instance_and_static){
513                                 MemberInfo [] i_members = t.FindMembers (
514                                         mt, bf & ~BindingFlags.Static, filter, criteria);
515                                 MemberInfo [] s_members = t.FindMembers (
516                                         mt, bf & ~BindingFlags.Instance, filter, criteria);
517
518                                 int i_len = i_members.Length;
519                                 int s_len = s_members.Length;
520                                 if (i_len > 0 || s_len > 0){
521                                         MemberInfo [] both = new MemberInfo [i_len + s_len];
522
523                                         i_members.CopyTo (both, 0);
524                                         s_members.CopyTo (both, i_len);
525
526                                         return both;
527                                 } else
528                                         return i_members;
529                         }
530                         return t.FindMembers (mt, bf, filter, criteria);
531                 }
532
533                 //
534                 // FIXME: We should not have builder_to_blah everywhere,
535                 // we should just have a builder_to_findmemberizable
536                 // and have them implement a new ICanFindMembers interface
537                 //
538                 Enum e = (Enum) builder_to_enum [t];
539
540                 if (e != null)
541                         return e.FindMembers (mt, bf, filter, criteria);
542                 
543                 Delegate del = (Delegate) builder_to_delegate [t];
544
545                 if (del != null)
546                         return del.FindMembers (mt, bf, filter, criteria);
547
548                 Interface iface = (Interface) builder_to_interface [t];
549
550                 if (iface != null) 
551                         return iface.FindMembers (mt, bf, filter, criteria);
552                 
553                 TypeContainer tc = (TypeContainer) builder_to_container [t];
554
555                 if (tc != null)
556                         return tc.FindMembers (mt, bf, filter, criteria);
557
558                 return null;
559         }
560
561         public static bool IsBuiltinType (Type t)
562         {
563                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
564                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
565                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
566                     t == sbyte_type || t == byte_type || t == ushort_type)
567                         return true;
568                 else
569                         return false;
570         }
571
572         public static bool IsDelegateType (Type t)
573         {
574                 if (t.IsSubclassOf (TypeManager.delegate_type))
575                         return true;
576                 else
577                         return false;
578         }
579         
580         public static bool IsEnumType (Type t)
581         {
582                 if (t.IsSubclassOf (TypeManager.enum_type))
583                         return true;
584                 else
585                         return false;
586         }
587         
588         public static bool IsInterfaceType (Type t)
589         {
590                 Interface iface = (Interface) builder_to_interface [t];
591
592                 if (iface != null)
593                         return true;
594                 else
595                         return false;
596         }
597
598         /// <summary>
599         ///   Returns the User Defined Types
600         /// </summary>
601         public ArrayList UserTypes {
602                 get {
603                         return user_types;
604                 }
605         }
606
607         public Hashtable TypeContainers {
608                 get {
609                         return typecontainers;
610                 }
611         }
612
613         static Hashtable builder_to_constant;
614
615         public static void RegisterConstant (FieldBuilder fb, Const c)
616         {
617                 if (builder_to_constant == null)
618                         builder_to_constant = new PtrHashtable ();
619
620                 if (builder_to_constant.Contains (fb))
621                         return;
622
623                 builder_to_constant.Add (fb, c);
624         }
625
626         public static Const LookupConstant (FieldBuilder fb)
627         {
628                 if (builder_to_constant == null)
629                         return null;
630                 
631                 return (Const) builder_to_constant [fb];
632         }
633         
634         /// <summary>
635         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
636         /// </summary>
637         ///
638         /// <remarks>
639         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
640         ///   for anything which is dynamic, and we need this in a number of places,
641         ///   we register this information here, and use it afterwards.
642         /// </remarks>
643         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
644         {
645                 method_arguments.Add (mb, args);
646                 method_internal_params.Add (mb, ip);
647                 
648                 return true;
649         }
650         
651         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
652         {
653                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
654                         return null;
655                 
656                 if (method_internal_params.Contains (mb))
657                         return (InternalParameters) method_internal_params [mb];
658                 else
659                         throw new Exception ("Argument for Method not registered" + mb);
660         }
661
662         /// <summary>
663         ///    Returns the argument types for a method based on its methodbase
664         ///
665         ///    For dynamic methods, we use the compiler provided types, for
666         ///    methods from existing assemblies we load them from GetParameters,
667         ///    and insert them into the cache
668         /// </summary>
669         static public Type [] GetArgumentTypes (MethodBase mb)
670         {
671                 if (method_arguments.Contains (mb))
672                         return (Type []) method_arguments [mb];
673                 else {
674                         ParameterInfo [] pi = mb.GetParameters ();
675                         int c = pi.Length;
676                         Type [] types = new Type [c];
677                         
678                         for (int i = 0; i < c; i++)
679                                 types [i] = pi [i].ParameterType;
680
681                         method_arguments.Add (mb, types);
682                         return types;
683                 }
684         }
685         
686         // <remarks>
687         //  This is a workaround the fact that GetValue is not
688         //  supported for dynamic types
689         // </remarks>
690         static Hashtable fields = new Hashtable ();
691         static public bool RegisterFieldValue (FieldBuilder fb, object value)
692         {
693                 if (fields.Contains (fb))
694                         return false;
695
696                 fields.Add (fb, value);
697
698                 return true;
699         }
700
701         static public object GetValue (FieldBuilder fb)
702         {
703                 return fields [fb];
704         }
705
706         static Hashtable fieldbuilders_to_fields = new Hashtable ();
707         static public bool RegisterField (FieldBuilder fb, Field f)
708         {
709                 if (fieldbuilders_to_fields.Contains (fb))
710                         return false;
711
712                 fieldbuilders_to_fields.Add (fb, f);
713                 return true;
714         }
715
716         static public Field GetField (FieldInfo fb)
717         {
718                 return (Field) fieldbuilders_to_fields [fb];
719         }
720         
721         static Hashtable events;
722
723         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
724         {
725                 if (events == null)
726                         events = new Hashtable ();
727
728                 if (events.Contains (eb))
729                         return false;
730
731                 events.Add (eb, new Pair (add, remove));
732
733                 return true;
734         }
735
736         static public MethodInfo GetAddMethod (EventInfo ei)
737         {
738                 if (ei is MyEventBuilder) {
739                         Pair pair = (Pair) events [ei];
740
741                         return (MethodInfo) pair.First;
742                 } else
743                         return ei.GetAddMethod ();
744         }
745
746         static public MethodInfo GetRemoveMethod (EventInfo ei)
747         {
748                 if (ei is MyEventBuilder) {
749                         Pair pair = (Pair) events [ei];
750
751                         return (MethodInfo) pair.Second;
752                 } else
753                         return ei.GetAddMethod ();
754         }
755
756         static Hashtable properties;
757         
758         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
759         {
760                 if (properties == null)
761                         properties = new Hashtable ();
762
763                 if (properties.Contains (pb))
764                         return false;
765
766                 properties.Add (pb, new Pair (get, set));
767
768                 return true;
769         }
770         
771         //
772         // FIXME: we need to return the accessors depending on whether
773         // they are visible or not.
774         //
775         static public MethodInfo [] GetAccessors (PropertyInfo pi)
776         {
777                 MethodInfo [] ret;
778
779                 if (pi is PropertyBuilder){
780                         Pair pair = (Pair) properties [pi];
781
782                         ret = new MethodInfo [2];
783                         ret [0] = (MethodInfo) pair.First;
784                         ret [1] = (MethodInfo) pair.Second;
785
786                         return ret;
787                 } else {
788                         MethodInfo [] mi = new MethodInfo [2];
789
790                         //
791                         // Why this and not pi.GetAccessors?
792                         // Because sometimes index 0 is the getter
793                         // sometimes it is 1
794                         //
795                         mi [0] = pi.GetGetMethod (true);
796                         mi [1] = pi.GetSetMethod (true);
797
798                         return mi;
799                 }
800         }
801
802         static public MethodInfo GetPropertyGetter (PropertyInfo pi)
803         {
804                 if (pi is PropertyBuilder){
805                         Pair de = (Pair) properties [pi];
806
807                         return (MethodInfo) de.Second;
808                 } else
809                         return pi.GetSetMethod ();
810         }
811
812         static public MethodInfo GetPropertySetter (PropertyInfo pi)
813         {
814                 if (pi is PropertyBuilder){
815                         Pair de = (Pair) properties [pi];
816
817                         return (MethodInfo) de.First;
818                 } else
819                         return pi.GetGetMethod ();
820         }
821                                 
822         // <remarks>
823         //  The following is used to check if a given type implements an interface.
824         //  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
825         // </remarks>
826
827         static Hashtable type_interface_cache;
828         public static bool ImplementsInterface (Type t, Type iface)
829         {
830                 Type [] interfaces;
831
832                 do {
833                         interfaces = t.GetInterfaces ();
834
835                         for (int i = interfaces.Length; i > 0; ){
836                                 i--;
837                                 if (interfaces [i] == iface)
838                                         return true;
839                         }
840                         t = t.BaseType;
841                 } while (t != null);
842                 
843                 return false;
844         }
845
846         //
847         // This is needed, because enumerations from assemblies
848         // do not report their underlyingtype, but they report
849         // themselves
850         //
851         public static Type EnumToUnderlying (Type t)
852         {
853                 t = t.UnderlyingSystemType;
854                 if (!TypeManager.IsEnumType (t))
855                         return t;
856                 
857                 TypeCode tc = Type.GetTypeCode (t);
858
859                 switch (tc){
860                 case TypeCode.Boolean:
861                         return TypeManager.bool_type;
862                 case TypeCode.Byte:
863                         return TypeManager.byte_type;
864                 case TypeCode.SByte:
865                         return TypeManager.sbyte_type;
866                 case TypeCode.Char:
867                         return TypeManager.char_type;
868                 case TypeCode.Int16:
869                         return TypeManager.short_type;
870                 case TypeCode.UInt16:
871                         return TypeManager.ushort_type;
872                 case TypeCode.Int32:
873                         return TypeManager.int32_type;
874                 case TypeCode.UInt32:
875                         return TypeManager.uint32_type;
876                 case TypeCode.Int64:
877                         return TypeManager.int64_type;
878                 case TypeCode.UInt64:
879                         return TypeManager.uint64_type;
880                 }
881                 throw new Exception ("Unhandled typecode in enum" + tc);
882         }
883         
884         /// <summary>
885         ///   Returns the name of the indexer in a given type.
886         /// </summary>
887         /// <remarks>
888         ///   The default is not always `Item'.  The user can change this behaviour by
889         ///   using the DefaultMemberAttribute in the class.
890         ///
891         ///   For example, the String class indexer is named `Chars' not `Item' 
892         /// </remarks>
893         public static string IndexerPropertyName (Type t)
894         {
895                 
896                 if (t is TypeBuilder) {
897                         TypeContainer tc = (TypeContainer) builder_to_container [t];
898
899                         Attributes attrs = tc.OptAttributes;
900                         
901                         if (attrs == null || attrs.AttributeSections == null)
902                                 return "Item";
903
904                         foreach (AttributeSection asec in attrs.AttributeSections) {
905
906                                 if (asec.Attributes == null)
907                                         continue;
908
909                                 foreach (Attribute a in asec.Attributes) {
910                                         if (a.Name.IndexOf ("DefaultMember") != -1) {
911                                                 ArrayList pos_args = (ArrayList) a.Arguments [0];
912                                                 Expression e = ((Argument) pos_args [0]).expr;
913
914                                                 if (e is StringConstant)
915                                                         return ((StringConstant) e).Value;
916                                         }
917                                 }
918                         }
919
920                         return "Item";
921                 }
922                 
923                 System.Attribute attr = System.Attribute.GetCustomAttribute (t, TypeManager.default_member_type);
924                 
925                 if (attr != null)
926                 {
927                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
928                         
929                         return dma.MemberName;
930                 }
931
932                 return "Item";
933         }
934
935 }
936
937 }