2 // typemanager.cs: C# type manager
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change
15 // the behavior of the compilation. This can be removed if we rework
16 // the code to get a list of namespaces available.
18 #define SIMPLE_SPEEDUP
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
31 namespace Mono.CSharp {
33 public class TypeManager {
35 // A list of core types that the compiler requires or uses
37 static public Type object_type;
38 static public Type value_type;
39 static public Type string_type;
40 static public Type int32_type;
41 static public Type uint32_type;
42 static public Type int64_type;
43 static public Type uint64_type;
44 static public Type float_type;
45 static public Type double_type;
46 static public Type char_type;
47 static public Type char_ptr_type;
48 static public Type short_type;
49 static public Type decimal_type;
50 static public Type bool_type;
51 static public Type sbyte_type;
52 static public Type byte_type;
53 static public Type ushort_type;
54 static public Type enum_type;
55 static public Type delegate_type;
56 static public Type multicast_delegate_type;
57 static public Type void_type;
58 static public Type enumeration_type;
59 static public Type array_type;
60 static public Type runtime_handle_type;
61 static public Type icloneable_type;
62 static public Type type_type;
63 static public Type ienumerator_type;
64 static public Type ienumerable_type;
65 static public Type idisposable_type;
66 static public Type default_member_type;
67 static public Type iasyncresult_type;
68 static public Type asynccallback_type;
69 static public Type intptr_type;
70 static public Type monitor_type;
71 static public Type runtime_field_handle_type;
72 static public Type attribute_type;
73 static public Type attribute_usage_type;
74 static public Type dllimport_type;
75 static public Type unverifiable_code_type;
76 static public Type methodimpl_attr_type;
77 static public Type marshal_as_attr_type;
78 static public Type param_array_type;
79 static public Type guid_attr_type;
80 static public Type void_ptr_type;
81 static public Type indexer_name_type;
82 static public Type exception_type;
83 static public Type invalid_operation_exception_type;
84 static public object obsolete_attribute_type;
85 static public object conditional_attribute_type;
86 static public Type in_attribute_type;
89 // An empty array of types
91 static public Type [] NoTypes;
92 static public TypeExpr [] NoTypeExprs;
96 // Expressions representing the internal types. Used during declaration
99 static public TypeExpr system_object_expr, system_string_expr;
100 static public TypeExpr system_boolean_expr, system_decimal_expr;
101 static public TypeExpr system_single_expr, system_double_expr;
102 static public TypeExpr system_sbyte_expr, system_byte_expr;
103 static public TypeExpr system_int16_expr, system_uint16_expr;
104 static public TypeExpr system_int32_expr, system_uint32_expr;
105 static public TypeExpr system_int64_expr, system_uint64_expr;
106 static public TypeExpr system_char_expr, system_void_expr;
107 static public TypeExpr system_asynccallback_expr;
108 static public TypeExpr system_iasyncresult_expr;
109 static public TypeExpr system_valuetype_expr;
112 // This is only used when compiling corlib
114 static public Type system_int32_type;
115 static public Type system_array_type;
116 static public Type system_type_type;
117 static public Type system_assemblybuilder_type;
118 static public MethodInfo system_int_array_get_length;
119 static public MethodInfo system_int_array_get_rank;
120 static public MethodInfo system_object_array_clone;
121 static public MethodInfo system_int_array_get_length_int;
122 static public MethodInfo system_int_array_get_lower_bound_int;
123 static public MethodInfo system_int_array_get_upper_bound_int;
124 static public MethodInfo system_void_array_copyto_array_int;
128 // Internal, not really used outside
130 static Type runtime_helpers_type;
133 // These methods are called by code generated by the compiler
135 static public MethodInfo string_concat_string_string;
136 static public MethodInfo string_concat_string_string_string;
137 static public MethodInfo string_concat_string_string_string_string;
138 static public MethodInfo string_concat_object_object;
139 static public MethodInfo string_isinterneted_string;
140 static public MethodInfo system_type_get_type_from_handle;
141 static public MethodInfo object_getcurrent_void;
142 static public MethodInfo bool_movenext_void;
143 static public MethodInfo ienumerable_getenumerator_void;
144 static public MethodInfo void_reset_void;
145 static public MethodInfo void_dispose_void;
146 static public MethodInfo void_monitor_enter_object;
147 static public MethodInfo void_monitor_exit_object;
148 static public MethodInfo void_initializearray_array_fieldhandle;
149 static public MethodInfo int_getlength_int;
150 static public MethodInfo delegate_combine_delegate_delegate;
151 static public MethodInfo delegate_remove_delegate_delegate;
152 static public MethodInfo int_get_offset_to_string_data;
153 static public MethodInfo int_array_get_length;
154 static public MethodInfo int_array_get_rank;
155 static public MethodInfo object_array_clone;
156 static public MethodInfo int_array_get_length_int;
157 static public MethodInfo int_array_get_lower_bound_int;
158 static public MethodInfo int_array_get_upper_bound_int;
159 static public MethodInfo void_array_copyto_array_int;
162 // The attribute constructors.
164 static public ConstructorInfo object_ctor;
165 static public ConstructorInfo cons_param_array_attribute;
166 static public ConstructorInfo void_decimal_ctor_five_args;
167 static public ConstructorInfo unverifiable_code_ctor;
168 static public ConstructorInfo invalid_operation_ctor;
171 // Holds the Array of Assemblies that have been loaded
172 // (either because it is the default or the user used the
173 // -r command line option)
175 static Assembly [] assemblies;
178 // Keeps a list of modules. We used this to do lookups
179 // on the module using GetType -- needed for arrays
181 static Module [] modules;
184 // This is the type_cache from the assemblies to avoid
185 // hitting System.Reflection on every lookup.
187 static Hashtable types;
190 // This is used to hotld the corresponding TypeContainer objects
191 // since we need this in FindMembers
193 static Hashtable typecontainers;
196 // Keeps track of those types that are defined by the
199 static ArrayList user_types;
201 static PtrHashtable builder_to_declspace;
204 // Tracks the interfaces implemented by typebuilders. We only
205 // enter those who do implement or or more interfaces
207 static PtrHashtable builder_to_ifaces;
210 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
211 // the arguments to the method
213 static Hashtable method_arguments;
216 // Maps PropertyBuilder to a Type array that contains
217 // the arguments to the indexer
219 static Hashtable indexer_arguments;
222 // Maybe `method_arguments' should be replaced and only
223 // method_internal_params should be kept?
225 static Hashtable method_internal_params;
228 // Keeps track of attribute types
231 static Hashtable builder_to_attr;
234 // Keeps track of methods
237 static Hashtable builder_to_method;
244 public static void CleanUp ()
246 // Lets get everything clean so that we can collect before generating code
250 typecontainers = null;
252 builder_to_declspace = null;
253 builder_to_ifaces = null;
254 method_arguments = null;
255 indexer_arguments = null;
256 method_internal_params = null;
257 builder_to_attr = null;
258 builder_to_method = null;
262 negative_hits = null;
263 attr_to_allowmult = null;
264 builder_to_constant = null;
265 fieldbuilders_to_fields = null;
267 priv_fields_events = null;
270 TypeHandle.CleanUp ();
274 /// A filter for Findmembers that uses the Signature object to
277 static bool SignatureFilter (MemberInfo mi, object criteria)
279 Signature sig = (Signature) criteria;
281 if (!(mi is MethodBase))
284 if (mi.Name != sig.name)
287 int count = sig.args.Length;
289 if (mi is MethodBuilder || mi is ConstructorBuilder){
290 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
292 if (candidate_args.Length != count)
295 for (int i = 0; i < count; i++)
296 if (candidate_args [i] != sig.args [i])
301 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
303 if (pars.Length != count)
306 for (int i = 0; i < count; i++)
307 if (pars [i].ParameterType != sig.args [i])
313 // A delegate that points to the filter above.
314 static MemberFilter signature_filter;
317 // These are expressions that represent some of the internal data types, used
320 static void InitExpressionTypes ()
322 system_object_expr = new TypeLookupExpression ("System.Object");
323 system_string_expr = new TypeLookupExpression ("System.String");
324 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
325 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
326 system_single_expr = new TypeLookupExpression ("System.Single");
327 system_double_expr = new TypeLookupExpression ("System.Double");
328 system_sbyte_expr = new TypeLookupExpression ("System.SByte");
329 system_byte_expr = new TypeLookupExpression ("System.Byte");
330 system_int16_expr = new TypeLookupExpression ("System.Int16");
331 system_uint16_expr = new TypeLookupExpression ("System.UInt16");
332 system_int32_expr = new TypeLookupExpression ("System.Int32");
333 system_uint32_expr = new TypeLookupExpression ("System.UInt32");
334 system_int64_expr = new TypeLookupExpression ("System.Int64");
335 system_uint64_expr = new TypeLookupExpression ("System.UInt64");
336 system_char_expr = new TypeLookupExpression ("System.Char");
337 system_void_expr = new TypeLookupExpression ("System.Void");
338 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
339 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
340 system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
343 static TypeManager ()
345 assemblies = new Assembly [0];
347 user_types = new ArrayList ();
349 types = new Hashtable ();
350 typecontainers = new Hashtable ();
352 builder_to_declspace = new PtrHashtable ();
353 builder_to_attr = new PtrHashtable ();
354 builder_to_method = new PtrHashtable ();
355 method_arguments = new PtrHashtable ();
356 method_internal_params = new PtrHashtable ();
357 indexer_arguments = new PtrHashtable ();
358 builder_to_ifaces = new PtrHashtable ();
360 NoTypes = new Type [0];
361 NoTypeExprs = new TypeExpr [0];
363 signature_filter = new MemberFilter (SignatureFilter);
364 InitExpressionTypes ();
367 public static void HandleDuplicate (string name, Type t)
369 Type prev = (Type) types [name];
370 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
374 // This probably never happens, as we catch this before
376 Report.Error (-17, "The type `" + name + "' has already been defined.");
380 tc = builder_to_declspace [t] as TypeContainer;
383 1595, "The type `" + name + "' is defined in an existing assembly;"+
384 " Using the new definition from: " + tc.Location);
387 1595, "The type `" + name + "' is defined in an existing assembly;");
390 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
396 public static void AddUserType (string name, TypeBuilder t, TypeExpr[] ifaces)
401 HandleDuplicate (name, t);
406 builder_to_ifaces [t] = ifaces;
410 // This entry point is used by types that we define under the covers
412 public static void RegisterBuilder (TypeBuilder tb, TypeExpr [] ifaces)
415 builder_to_ifaces [tb] = ifaces;
418 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, TypeExpr [] ifaces)
420 builder_to_declspace.Add (t, tc);
421 typecontainers.Add (name, tc);
422 AddUserType (name, t, ifaces);
425 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
430 HandleDuplicate (name, t);
433 builder_to_declspace.Add (t, del);
436 public static void AddEnumType (string name, TypeBuilder t, Enum en)
441 HandleDuplicate (name, t);
443 builder_to_declspace.Add (t, en);
446 public static void AddUserInterface (string name, TypeBuilder t, Interface i, TypeExpr [] ifaces)
448 AddUserType (name, t, ifaces);
449 builder_to_declspace.Add (t, i);
452 public static void AddMethod (MethodBuilder builder, MethodData method)
454 builder_to_method.Add (builder, method);
457 public static void RegisterAttrType (Type t, TypeContainer tc)
459 builder_to_attr.Add (t, tc);
463 /// Returns the DeclSpace whose Type is `t' or null if there is no
464 /// DeclSpace for `t' (ie, the Type comes from a library)
466 public static DeclSpace LookupDeclSpace (Type t)
468 return builder_to_declspace [t] as DeclSpace;
472 /// Returns the TypeContainer whose Type is `t' or null if there is no
473 /// TypeContainer for `t' (ie, the Type comes from a library)
475 public static TypeContainer LookupTypeContainer (Type t)
477 return builder_to_declspace [t] as TypeContainer;
480 public static IMemberContainer LookupMemberContainer (Type t)
482 if (t is TypeBuilder) {
483 IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
484 if (container != null)
488 return TypeHandle.GetTypeHandle (t);
491 public static Interface LookupInterface (Type t)
493 return builder_to_declspace [t] as Interface;
496 public static Delegate LookupDelegate (Type t)
498 return builder_to_declspace [t] as Delegate;
501 public static Enum LookupEnum (Type t)
503 return builder_to_declspace [t] as Enum;
506 public static TypeContainer LookupAttr (Type t)
508 return (TypeContainer) builder_to_attr [t];
512 /// Registers an assembly to load types from.
514 public static void AddAssembly (Assembly a)
516 int top = assemblies.Length;
517 Assembly [] n = new Assembly [top + 1];
519 assemblies.CopyTo (n, 0);
526 /// Registers a module builder to lookup types from
528 public static void AddModule (Module mb)
530 int top = modules != null ? modules.Length : 0;
531 Module [] n = new Module [top + 1];
534 modules.CopyTo (n, 0);
539 static Hashtable references = new Hashtable ();
542 // Gets the reference to T version of the Type (T&)
544 public static Type GetReferenceType (Type t)
546 string tname = t.FullName + "&";
548 Type ret = t.Assembly.GetType (tname);
551 // If the type comes from the assembly we are building
552 // We need the Hashtable, because .NET 1.1 will return different instance types
553 // every time we call ModuleBuilder.GetType.
556 if (references [t] == null)
557 references [t] = CodeGen.ModuleBuilder.GetType (tname);
558 ret = (Type) references [t];
564 static Hashtable pointers = new Hashtable ();
567 // Gets the pointer to T version of the Type (T*)
569 public static Type GetPointerType (Type t)
571 string tname = t.FullName + "*";
573 Type ret = t.Assembly.GetType (tname);
576 // If the type comes from the assembly we are building
577 // We need the Hashtable, because .NET 1.1 will return different instance types
578 // every time we call ModuleBuilder.GetType.
581 if (pointers [t] == null)
582 pointers [t] = CodeGen.ModuleBuilder.GetType (tname);
584 ret = (Type) pointers [t];
591 // Low-level lookup, cache-less
593 static Type LookupTypeReflection (string name)
597 foreach (Assembly a in assemblies){
598 t = a.GetType (name);
603 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
604 if (ta == TypeAttributes.NotPublic ||
605 ta == TypeAttributes.NestedPrivate ||
606 ta == TypeAttributes.NestedAssembly ||
607 ta == TypeAttributes.NestedFamANDAssem){
610 // In .NET pointers turn out to be private, even if their
611 // element type is not
614 t = t.GetElementType ();
624 foreach (Module mb in modules) {
625 t = mb.GetType (name);
633 static Hashtable negative_hits = new Hashtable ();
636 // This function is used when you want to avoid the lookups, and want to go
637 // directly to the source. This will use the cache.
639 // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
640 // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
641 // way to test things other than doing a fullname compare
643 public static Type LookupTypeDirect (string name)
645 Type t = (Type) types [name];
649 t = LookupTypeReflection (name);
657 static readonly char [] dot_array = { '.' };
660 /// Returns the Type associated with @name, takes care of the fact that
661 /// reflection expects nested types to be separated from the main type
662 /// with a "+" instead of a "."
664 public static Type LookupType (string name)
669 // First lookup in user defined and cached values
672 t = (Type) types [name];
676 // Two thirds of the failures are caught here.
677 if (negative_hits.Contains (name))
680 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
681 string [] elements = name.Split (dot_array);
682 int count = elements.Length;
684 for (int n = 1; n <= count; n++){
685 string top_level_type = String.Join (".", elements, 0, n);
687 // One third of the failures are caught here.
688 if (negative_hits.Contains (top_level_type))
691 t = (Type) types [top_level_type];
693 t = LookupTypeReflection (top_level_type);
695 negative_hits [top_level_type] = null;
706 // We know that System.Object does not have children, and since its the parent of
707 // all the objects, it always gets probbed for inner classes.
709 if (top_level_type == "System.Object")
712 string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
713 //Console.WriteLine ("Looking up: " + newt + " " + name);
714 t = LookupTypeReflection (newt);
716 negative_hits [name] = null;
721 negative_hits [name] = null;
726 /// Computes the namespaces that we import from the assemblies we reference.
728 public static void ComputeNamespaces ()
730 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
733 // First add the assembly namespaces
735 if (assembly_get_namespaces != null){
736 int count = assemblies.Length;
738 for (int i = 0; i < count; i++){
739 Assembly a = assemblies [i];
740 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
741 foreach (string ns in namespaces){
744 Namespace.LookupNamespace (ns, true);
748 foreach (Assembly a in assemblies){
749 foreach (Type t in a.GetTypes ()){
750 string ns = t.Namespace;
752 // t.Namespace returns null for <PrivateImplDetails>
753 if (ns == ""|| ns == null)
755 Namespace.LookupNamespace (ns, true);
761 public static bool NamespaceClash (string name, Location loc)
763 if (Namespace.LookupNamespace (name, false) == null)
766 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
771 /// Returns the C# name of a type if possible, or the full type name otherwise
773 static public string CSharpName (Type t)
775 return Regex.Replace (t.FullName,
777 @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
778 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
779 @"Boolean|String|Void)" +
781 new MatchEvaluator (CSharpNameMatch));
784 static String CSharpNameMatch (Match match)
786 string s = match.Groups [1].Captures [0].Value;
788 Replace ("int32", "int").
789 Replace ("uint32", "uint").
790 Replace ("int16", "short").
791 Replace ("uint16", "ushort").
792 Replace ("int64", "long").
793 Replace ("uint64", "ulong").
794 Replace ("single", "float").
795 Replace ("boolean", "bool")
796 + match.Groups [2].Captures [0].Value;
800 /// Returns the signature of the method
802 static public string CSharpSignature (MethodBase mb)
807 // FIXME: We should really have a single function to do
808 // everything instead of the following 5 line pattern
810 ParameterData iparams = LookupParametersByBuilder (mb);
812 if (iparams == null){
813 ParameterInfo [] pi = mb.GetParameters ();
814 iparams = new ReflectionParameters (pi);
817 for (int i = 0; i < iparams.Count; i++) {
821 sig += iparams.ParameterDesc(i);
825 return mb.DeclaringType.Name + "." + mb.Name + sig;
829 /// Looks up a type, and aborts if it is not found. This is used
830 /// by types required by the compiler
832 static Type CoreLookupType (string name)
834 Type t = LookupTypeDirect (name);
837 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
838 Environment.Exit (0);
845 /// Returns the MethodInfo for a method named `name' defined
846 /// in type `t' which takes arguments of types `args'
848 static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
852 BindingFlags flags = instance_and_static | BindingFlags.Public;
858 flags |= BindingFlags.NonPublic;
860 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
861 if (list.Count == 0) {
863 Report.Error (-19, "Can not find the core function `" + name + "'");
867 MethodInfo mi = list [0] as MethodInfo;
870 Report.Error (-19, "Can not find the core function `" + name + "'");
877 static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
879 return GetMethod (t, name, args, false, report_errors);
882 static MethodInfo GetMethod (Type t, string name, Type [] args)
884 return GetMethod (t, name, args, true);
889 /// Returns the ConstructorInfo for "args"
891 static ConstructorInfo GetConstructor (Type t, Type [] args)
899 list = FindMembers (t, MemberTypes.Constructor,
900 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
901 signature_filter, sig);
902 if (list.Count == 0){
903 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
907 ConstructorInfo ci = list [0] as ConstructorInfo;
909 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
916 public static void InitEnumUnderlyingTypes ()
919 int32_type = CoreLookupType ("System.Int32");
920 int64_type = CoreLookupType ("System.Int64");
921 uint32_type = CoreLookupType ("System.UInt32");
922 uint64_type = CoreLookupType ("System.UInt64");
923 byte_type = CoreLookupType ("System.Byte");
924 sbyte_type = CoreLookupType ("System.SByte");
925 short_type = CoreLookupType ("System.Int16");
926 ushort_type = CoreLookupType ("System.UInt16");
930 /// The types have to be initialized after the initial
931 /// population of the type has happened (for example, to
932 /// bootstrap the corlib.dll
934 public static void InitCoreTypes ()
936 object_type = CoreLookupType ("System.Object");
937 value_type = CoreLookupType ("System.ValueType");
939 InitEnumUnderlyingTypes ();
941 char_type = CoreLookupType ("System.Char");
942 string_type = CoreLookupType ("System.String");
943 float_type = CoreLookupType ("System.Single");
944 double_type = CoreLookupType ("System.Double");
945 char_ptr_type = CoreLookupType ("System.Char*");
946 decimal_type = CoreLookupType ("System.Decimal");
947 bool_type = CoreLookupType ("System.Boolean");
948 enum_type = CoreLookupType ("System.Enum");
950 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
951 delegate_type = CoreLookupType ("System.Delegate");
953 array_type = CoreLookupType ("System.Array");
954 void_type = CoreLookupType ("System.Void");
955 type_type = CoreLookupType ("System.Type");
957 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
958 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
959 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
960 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
961 asynccallback_type = CoreLookupType ("System.AsyncCallback");
962 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
963 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
964 ienumerable_type = CoreLookupType ("System.Collections.IEnumerable");
965 idisposable_type = CoreLookupType ("System.IDisposable");
966 icloneable_type = CoreLookupType ("System.ICloneable");
967 monitor_type = CoreLookupType ("System.Threading.Monitor");
968 intptr_type = CoreLookupType ("System.IntPtr");
970 attribute_type = CoreLookupType ("System.Attribute");
971 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
972 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
973 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
974 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
975 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
976 in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
979 // Sigh. Remove this before the release. Wonder what versions of Mono
980 // people are running.
982 guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute");
984 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
986 void_ptr_type = CoreLookupType ("System.Void*");
988 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
990 exception_type = CoreLookupType ("System.Exception");
991 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
996 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
997 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1000 // When compiling corlib, store the "real" types here.
1002 if (!RootContext.StdLib) {
1003 system_int32_type = typeof (System.Int32);
1004 system_array_type = typeof (System.Array);
1005 system_type_type = typeof (System.Type);
1006 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1008 Type [] void_arg = { };
1009 system_int_array_get_length = GetMethod (
1010 system_array_type, "get_Length", void_arg);
1011 system_int_array_get_rank = GetMethod (
1012 system_array_type, "get_Rank", void_arg);
1013 system_object_array_clone = GetMethod (
1014 system_array_type, "Clone", void_arg);
1016 Type [] system_int_arg = { system_int32_type };
1017 system_int_array_get_length_int = GetMethod (
1018 system_array_type, "GetLength", system_int_arg);
1019 system_int_array_get_upper_bound_int = GetMethod (
1020 system_array_type, "GetUpperBound", system_int_arg);
1021 system_int_array_get_lower_bound_int = GetMethod (
1022 system_array_type, "GetLowerBound", system_int_arg);
1024 Type [] system_array_int_arg = { system_array_type, system_int32_type };
1025 system_void_array_copyto_array_int = GetMethod (
1026 system_array_type, "CopyTo", system_array_int_arg);
1028 Type [] system_3_type_arg = {
1029 system_type_type, system_type_type, system_type_type };
1030 Type [] system_4_type_arg = {
1031 system_type_type, system_type_type, system_type_type, system_type_type };
1033 MethodInfo set_corlib_type_builders = GetMethod (
1034 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1035 system_4_type_arg, true, false);
1037 if (set_corlib_type_builders != null) {
1038 object[] args = new object [4];
1039 args [0] = object_type;
1040 args [1] = value_type;
1041 args [2] = enum_type;
1042 args [3] = void_type;
1044 set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
1046 // Compatibility for an older version of the class libs.
1047 set_corlib_type_builders = GetMethod (
1048 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1049 system_3_type_arg, true, true);
1051 if (set_corlib_type_builders == null) {
1052 Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1056 object[] args = new object [3];
1057 args [0] = object_type;
1058 args [1] = value_type;
1059 args [2] = enum_type;
1061 set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
1065 system_object_expr.Type = object_type;
1066 system_string_expr.Type = string_type;
1067 system_boolean_expr.Type = bool_type;
1068 system_decimal_expr.Type = decimal_type;
1069 system_single_expr.Type = float_type;
1070 system_double_expr.Type = double_type;
1071 system_sbyte_expr.Type = sbyte_type;
1072 system_byte_expr.Type = byte_type;
1073 system_int16_expr.Type = short_type;
1074 system_uint16_expr.Type = ushort_type;
1075 system_int32_expr.Type = int32_type;
1076 system_uint32_expr.Type = uint32_type;
1077 system_int64_expr.Type = int64_type;
1078 system_uint64_expr.Type = uint64_type;
1079 system_char_expr.Type = char_type;
1080 system_void_expr.Type = void_type;
1081 system_asynccallback_expr.Type = asynccallback_type;
1082 system_iasyncresult_expr.Type = iasyncresult_type;
1083 system_valuetype_expr.Type = value_type;
1087 // The helper methods that are used by the compiler
1089 public static void InitCodeHelpers ()
1092 // Now load the default methods that we use.
1094 Type [] string_string = { string_type, string_type };
1095 string_concat_string_string = GetMethod (
1096 string_type, "Concat", string_string);
1097 Type [] string_string_string = { string_type, string_type, string_type };
1098 string_concat_string_string_string = GetMethod (
1099 string_type, "Concat", string_string_string);
1100 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1101 string_concat_string_string_string_string = GetMethod (
1102 string_type, "Concat", string_string_string_string);
1104 Type [] object_object = { object_type, object_type };
1105 string_concat_object_object = GetMethod (
1106 string_type, "Concat", object_object);
1108 Type [] string_ = { string_type };
1109 string_isinterneted_string = GetMethod (
1110 string_type, "IsInterned", string_);
1112 Type [] runtime_type_handle = { runtime_handle_type };
1113 system_type_get_type_from_handle = GetMethod (
1114 type_type, "GetTypeFromHandle", runtime_type_handle);
1116 Type [] delegate_delegate = { delegate_type, delegate_type };
1117 delegate_combine_delegate_delegate = GetMethod (
1118 delegate_type, "Combine", delegate_delegate);
1120 delegate_remove_delegate_delegate = GetMethod (
1121 delegate_type, "Remove", delegate_delegate);
1126 Type [] void_arg = { };
1127 object_getcurrent_void = GetMethod (
1128 ienumerator_type, "get_Current", void_arg);
1129 bool_movenext_void = GetMethod (
1130 ienumerator_type, "MoveNext", void_arg);
1131 void_reset_void = GetMethod (
1132 ienumerator_type, "Reset", void_arg);
1133 void_dispose_void = GetMethod (
1134 idisposable_type, "Dispose", void_arg);
1135 int_get_offset_to_string_data = GetMethod (
1136 runtime_helpers_type, "get_OffsetToStringData", void_arg);
1137 int_array_get_length = GetMethod (
1138 array_type, "get_Length", void_arg);
1139 int_array_get_rank = GetMethod (
1140 array_type, "get_Rank", void_arg);
1141 ienumerable_getenumerator_void = GetMethod (
1142 ienumerable_type, "GetEnumerator", void_arg);
1147 Type [] int_arg = { int32_type };
1148 int_array_get_length_int = GetMethod (
1149 array_type, "GetLength", int_arg);
1150 int_array_get_upper_bound_int = GetMethod (
1151 array_type, "GetUpperBound", int_arg);
1152 int_array_get_lower_bound_int = GetMethod (
1153 array_type, "GetLowerBound", int_arg);
1156 // System.Array methods
1158 object_array_clone = GetMethod (
1159 array_type, "Clone", void_arg);
1160 Type [] array_int_arg = { array_type, int32_type };
1161 void_array_copyto_array_int = GetMethod (
1162 array_type, "CopyTo", array_int_arg);
1167 Type [] object_arg = { object_type };
1168 void_monitor_enter_object = GetMethod (
1169 monitor_type, "Enter", object_arg);
1170 void_monitor_exit_object = GetMethod (
1171 monitor_type, "Exit", object_arg);
1173 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1175 void_initializearray_array_fieldhandle = GetMethod (
1176 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1181 int_getlength_int = GetMethod (
1182 array_type, "GetLength", int_arg);
1185 // Decimal constructors
1187 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1188 void_decimal_ctor_five_args = GetConstructor (
1189 decimal_type, dec_arg);
1194 cons_param_array_attribute = GetConstructor (
1195 param_array_type, void_arg);
1197 unverifiable_code_ctor = GetConstructor (
1198 unverifiable_code_type, void_arg);
1201 // InvalidOperationException
1203 invalid_operation_ctor = GetConstructor (
1204 invalid_operation_exception_type, void_arg);
1208 object_ctor = GetConstructor (object_type, void_arg);
1212 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1215 /// This is the "old", non-cache based FindMembers() function. We cannot use
1216 /// the cache here because there is no member name argument.
1218 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1219 MemberFilter filter, object criteria)
1221 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1224 // `builder_to_declspace' contains all dynamic types.
1228 Timer.StartTimer (TimerType.FindMembers);
1229 list = decl.FindMembers (mt, bf, filter, criteria);
1230 Timer.StopTimer (TimerType.FindMembers);
1235 // We have to take care of arrays specially, because GetType on
1236 // a TypeBuilder array will return a Type, not a TypeBuilder,
1237 // and we can not call FindMembers on this type.
1239 if (t.IsSubclassOf (TypeManager.array_type))
1240 return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1243 // Since FindMembers will not lookup both static and instance
1244 // members, we emulate this behaviour here.
1246 if ((bf & instance_and_static) == instance_and_static){
1247 MemberInfo [] i_members = t.FindMembers (
1248 mt, bf & ~BindingFlags.Static, filter, criteria);
1250 int i_len = i_members.Length;
1252 MemberInfo one = i_members [0];
1255 // If any of these are present, we are done!
1257 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1258 return new MemberList (i_members);
1261 MemberInfo [] s_members = t.FindMembers (
1262 mt, bf & ~BindingFlags.Instance, filter, criteria);
1264 int s_len = s_members.Length;
1265 if (i_len > 0 || s_len > 0)
1266 return new MemberList (i_members, s_members);
1269 return new MemberList (i_members);
1271 return new MemberList (s_members);
1275 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1280 /// This method is only called from within MemberLookup. It tries to use the member
1281 /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
1282 /// flag tells the caller whether we used the cache or not. If we used the cache, then
1283 /// our return value will already contain all inherited members and the caller don't need
1284 /// to check base classes and interfaces anymore.
1286 private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1287 string name, out bool used_cache)
1290 // We have to take care of arrays specially, because GetType on
1291 // a TypeBuilder array will return a Type, not a TypeBuilder,
1292 // and we can not call FindMembers on this type.
1294 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1296 return TypeHandle.ArrayType.MemberCache.FindMembers (
1297 mt, bf, name, FilterWithClosure_delegate, null);
1301 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1302 // and we can ask the DeclSpace for the MemberCache.
1304 if (t is TypeBuilder) {
1305 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1306 MemberCache cache = decl.MemberCache;
1309 // If this DeclSpace has a MemberCache, use it.
1312 if (cache != null) {
1314 return cache.FindMembers (
1315 mt, bf, name, FilterWithClosure_delegate, null);
1318 // If there is no MemberCache, we need to use the "normal" FindMembers.
1321 Timer.StartTimer (TimerType.FindMembers);
1322 list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1323 FilterWithClosure_delegate, name);
1324 Timer.StopTimer (TimerType.FindMembers);
1331 // This call will always succeed. There is exactly one TypeHandle instance per
1332 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1333 // if it didn't already exist.
1335 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1338 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1341 public static bool IsBuiltinType (Type t)
1343 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1344 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1345 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1346 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1353 // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1354 // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1356 public static bool IsCLRType (Type t)
1358 if (t == object_type || t == int32_type || t == uint32_type ||
1359 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1360 t == char_type || t == short_type || t == bool_type ||
1361 t == sbyte_type || t == byte_type || t == ushort_type)
1367 public static bool IsDelegateType (Type t)
1369 if (t.IsSubclassOf (TypeManager.delegate_type))
1375 public static bool IsEnumType (Type t)
1377 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1382 public static bool IsBuiltinOrEnum (Type t)
1384 if (IsBuiltinType (t))
1394 // Whether a type is unmanaged. This is used by the unsafe code (25.2)
1396 public static bool IsUnmanagedType (Type t)
1398 if (IsBuiltinType (t) && t != TypeManager.string_type)
1407 if (IsValueType (t)){
1408 if (t is TypeBuilder){
1409 TypeContainer tc = LookupTypeContainer (t);
1411 foreach (Field f in tc.Fields){
1412 if (f.FieldBuilder.IsStatic)
1414 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1418 FieldInfo [] fields = t.GetFields ();
1420 foreach (FieldInfo f in fields){
1423 if (!IsUnmanagedType (f.FieldType))
1433 public static bool IsValueType (Type t)
1435 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1441 public static bool IsInterfaceType (Type t)
1443 Interface iface = builder_to_declspace [t] as Interface;
1452 // Checks whether `type' is a subclass or nested child of `parent'.
1454 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1457 if ((type == parent) || type.IsSubclassOf (parent))
1460 // Handle nested types.
1461 type = type.DeclaringType;
1462 } while (type != null);
1468 // Checks whether `type' is a nested child of `parent'.
1470 public static bool IsNestedChildOf (Type type, Type parent)
1475 type = type.DeclaringType;
1476 while (type != null) {
1480 type = type.DeclaringType;
1487 // Do the right thing when returning the element type of an
1488 // array type based on whether we are compiling corlib or not
1490 public static Type GetElementType (Type t)
1492 if (RootContext.StdLib)
1493 return t.GetElementType ();
1495 return TypeToCoreType (t.GetElementType ());
1499 /// Returns the User Defined Types
1501 public static ArrayList UserTypes {
1507 public static Hashtable TypeContainers {
1509 return typecontainers;
1513 static Hashtable attr_to_allowmult;
1515 public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
1517 if (attr_to_allowmult == null)
1518 attr_to_allowmult = new PtrHashtable ();
1520 if (attr_to_allowmult.Contains (attr_type))
1523 attr_to_allowmult.Add (attr_type, allow);
1527 public static bool AreMultipleAllowed (Type attr_type)
1529 if (!(attr_type is TypeBuilder)) {
1530 System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
1532 foreach (System.Attribute tmp in attrs)
1533 if (tmp is AttributeUsageAttribute) {
1534 return ((AttributeUsageAttribute) tmp).AllowMultiple;
1540 if (attr_to_allowmult == null)
1543 return (bool) attr_to_allowmult [attr_type];
1546 static Hashtable builder_to_constant;
1548 public static void RegisterConstant (FieldBuilder fb, Const c)
1550 if (builder_to_constant == null)
1551 builder_to_constant = new PtrHashtable ();
1553 if (builder_to_constant.Contains (fb))
1556 builder_to_constant.Add (fb, c);
1559 public static Const LookupConstant (FieldBuilder fb)
1561 if (builder_to_constant == null)
1564 return (Const) builder_to_constant [fb];
1568 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1572 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1573 /// for anything which is dynamic, and we need this in a number of places,
1574 /// we register this information here, and use it afterwards.
1576 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1581 method_arguments.Add (mb, args);
1582 method_internal_params.Add (mb, ip);
1587 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1589 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1592 if (method_internal_params.Contains (mb))
1593 return (InternalParameters) method_internal_params [mb];
1595 throw new Exception ("Argument for Method not registered" + mb);
1599 /// Returns the argument types for a method based on its methodbase
1601 /// For dynamic methods, we use the compiler provided types, for
1602 /// methods from existing assemblies we load them from GetParameters,
1603 /// and insert them into the cache
1605 static public Type [] GetArgumentTypes (MethodBase mb)
1607 if (method_arguments.Contains (mb))
1608 return (Type []) method_arguments [mb];
1610 ParameterInfo [] pi = mb.GetParameters ();
1612 Type [] types = new Type [c];
1614 for (int i = 0; i < c; i++)
1615 types [i] = pi [i].ParameterType;
1617 method_arguments.Add (mb, types);
1623 /// Returns the argument types for an indexer based on its PropertyInfo
1625 /// For dynamic indexers, we use the compiler provided types, for
1626 /// indexers from existing assemblies we load them from GetParameters,
1627 /// and insert them into the cache
1629 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1631 if (indexer_arguments.Contains (indexer))
1632 return (Type []) indexer_arguments [indexer];
1633 else if (indexer is PropertyBuilder)
1634 // If we're a PropertyBuilder and not in the
1635 // `indexer_arguments' hash, then we're a property and
1639 ParameterInfo [] pi = indexer.GetIndexParameters ();
1640 // Property, not an indexer.
1644 Type [] types = new Type [c];
1646 for (int i = 0; i < c; i++)
1647 types [i] = pi [i].ParameterType;
1649 indexer_arguments.Add (indexer, types);
1655 // This is a workaround the fact that GetValue is not
1656 // supported for dynamic types
1658 static Hashtable fields = new Hashtable ();
1659 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1661 if (fields.Contains (fb))
1664 fields.Add (fb, value);
1669 static public object GetValue (FieldBuilder fb)
1674 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1675 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1677 if (fieldbuilders_to_fields.Contains (fb))
1680 fieldbuilders_to_fields.Add (fb, f);
1685 // The return value can be null; This will be the case for
1686 // auxiliary FieldBuilders created by the compiler that have no
1687 // real field being declared on the source code
1689 static public FieldBase GetField (FieldInfo fb)
1691 return (FieldBase) fieldbuilders_to_fields [fb];
1694 static Hashtable events;
1696 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1699 events = new Hashtable ();
1701 if (events.Contains (eb))
1704 events.Add (eb, new Pair (add, remove));
1709 static public MethodInfo GetAddMethod (EventInfo ei)
1711 if (ei is MyEventBuilder) {
1712 Pair pair = (Pair) events [ei];
1714 return (MethodInfo) pair.First;
1716 return ei.GetAddMethod ();
1719 static public MethodInfo GetRemoveMethod (EventInfo ei)
1721 if (ei is MyEventBuilder) {
1722 Pair pair = (Pair) events [ei];
1724 return (MethodInfo) pair.Second;
1726 return ei.GetRemoveMethod ();
1729 static Hashtable priv_fields_events;
1731 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1733 if (priv_fields_events == null)
1734 priv_fields_events = new Hashtable ();
1736 if (priv_fields_events.Contains (einfo))
1739 priv_fields_events.Add (einfo, builder);
1744 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1746 if (priv_fields_events == null)
1749 return (MemberInfo) priv_fields_events [ei];
1752 static Hashtable properties;
1754 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1756 if (properties == null)
1757 properties = new Hashtable ();
1759 if (properties.Contains (pb))
1762 properties.Add (pb, new Pair (get, set));
1767 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1768 MethodBase set, Type[] args)
1770 if (!RegisterProperty (pb, get,set))
1773 indexer_arguments.Add (pb, args);
1779 /// Given an array of interface types, expand and eliminate repeated ocurrences
1780 /// of an interface.
1784 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1787 public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
1789 ArrayList new_ifaces = new ArrayList ();
1791 foreach (TypeExpr iface in base_interfaces){
1792 if (!new_ifaces.Contains (iface))
1793 new_ifaces.Add (iface);
1795 TypeExpr [] implementing = iface.GetInterfaces ();
1797 foreach (TypeExpr imp in implementing){
1798 if (!new_ifaces.Contains (imp))
1799 new_ifaces.Add (imp);
1802 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
1803 new_ifaces.CopyTo (ret, 0);
1807 static PtrHashtable iface_cache = new PtrHashtable ();
1810 /// This function returns the interfaces in the type `t'. Works with
1811 /// both types and TypeBuilders.
1813 public static TypeExpr [] GetInterfaces (Type t)
1816 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
1821 // The reason for catching the Array case is that Reflection.Emit
1822 // will not return a TypeBuilder for Array types of TypeBuilder types,
1823 // but will still throw an exception if we try to call GetInterfaces
1826 // Since the array interfaces are always constant, we return those for
1831 t = TypeManager.array_type;
1833 if (t is TypeBuilder){
1834 TypeExpr [] parent_ifaces;
1836 if (t.BaseType == null)
1837 parent_ifaces = NoTypeExprs;
1839 parent_ifaces = GetInterfaces (t.BaseType);
1840 TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
1841 if (type_ifaces == null)
1842 type_ifaces = NoTypeExprs;
1844 int parent_count = parent_ifaces.Length;
1845 TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
1846 parent_ifaces.CopyTo (result, 0);
1847 type_ifaces.CopyTo (result, parent_count);
1849 iface_cache [t] = result;
1852 Type [] ifaces = t.GetInterfaces ();
1853 if (ifaces.Length == 0)
1856 TypeExpr [] result = new TypeExpr [ifaces.Length];
1857 for (int i = 0; i < ifaces.Length; i++)
1858 result [i] = new TypeExpression (ifaces [i], Location.Null);
1860 iface_cache [t] = result;
1866 // gets the interfaces that are declared explicitly on t
1868 public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
1870 return (TypeExpr []) builder_to_ifaces [t];
1874 /// The following is used to check if a given type implements an interface.
1875 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1877 public static bool ImplementsInterface (Type t, Type iface)
1879 TypeExpr [] interfaces;
1882 // FIXME OPTIMIZATION:
1883 // as soon as we hit a non-TypeBuiler in the interface
1884 // chain, we could return, as the `Type.GetInterfaces'
1885 // will return all the interfaces implement by the type
1889 interfaces = GetInterfaces (t);
1891 if (interfaces != null){
1892 foreach (TypeExpr i in interfaces){
1893 if (i.Type == iface)
1899 } while (t != null);
1904 static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
1906 // This is a custom version of Convert.ChangeType() which works
1907 // with the TypeBuilder defined types when compiling corlib.
1908 public static object ChangeType (object value, Type conversionType, out bool error)
1910 IConvertible convert_value = value as IConvertible;
1912 if (convert_value == null){
1918 // We must use Type.Equals() here since `conversionType' is
1919 // the TypeBuilder created version of a system type and not
1920 // the system type itself. You cannot use Type.GetTypeCode()
1921 // on such a type - it'd always return TypeCode.Object.
1925 if (conversionType.Equals (typeof (Boolean)))
1926 return (object)(convert_value.ToBoolean (nf_provider));
1927 else if (conversionType.Equals (typeof (Byte)))
1928 return (object)(convert_value.ToByte (nf_provider));
1929 else if (conversionType.Equals (typeof (Char)))
1930 return (object)(convert_value.ToChar (nf_provider));
1931 else if (conversionType.Equals (typeof (DateTime)))
1932 return (object)(convert_value.ToDateTime (nf_provider));
1933 else if (conversionType.Equals (typeof (Decimal)))
1934 return (object)(convert_value.ToDecimal (nf_provider));
1935 else if (conversionType.Equals (typeof (Double)))
1936 return (object)(convert_value.ToDouble (nf_provider));
1937 else if (conversionType.Equals (typeof (Int16)))
1938 return (object)(convert_value.ToInt16 (nf_provider));
1939 else if (conversionType.Equals (typeof (Int32)))
1940 return (object)(convert_value.ToInt32 (nf_provider));
1941 else if (conversionType.Equals (typeof (Int64)))
1942 return (object)(convert_value.ToInt64 (nf_provider));
1943 else if (conversionType.Equals (typeof (SByte)))
1944 return (object)(convert_value.ToSByte (nf_provider));
1945 else if (conversionType.Equals (typeof (Single)))
1946 return (object)(convert_value.ToSingle (nf_provider));
1947 else if (conversionType.Equals (typeof (String)))
1948 return (object)(convert_value.ToString (nf_provider));
1949 else if (conversionType.Equals (typeof (UInt16)))
1950 return (object)(convert_value.ToUInt16 (nf_provider));
1951 else if (conversionType.Equals (typeof (UInt32)))
1952 return (object)(convert_value.ToUInt32 (nf_provider));
1953 else if (conversionType.Equals (typeof (UInt64)))
1954 return (object)(convert_value.ToUInt64 (nf_provider));
1955 else if (conversionType.Equals (typeof (Object)))
1956 return (object)(value);
1966 // This is needed, because enumerations from assemblies
1967 // do not report their underlyingtype, but they report
1970 public static Type EnumToUnderlying (Type t)
1972 if (t == TypeManager.enum_type)
1975 t = t.UnderlyingSystemType;
1976 if (!TypeManager.IsEnumType (t))
1979 if (t is TypeBuilder) {
1980 // slow path needed to compile corlib
1981 if (t == TypeManager.bool_type ||
1982 t == TypeManager.byte_type ||
1983 t == TypeManager.sbyte_type ||
1984 t == TypeManager.char_type ||
1985 t == TypeManager.short_type ||
1986 t == TypeManager.ushort_type ||
1987 t == TypeManager.int32_type ||
1988 t == TypeManager.uint32_type ||
1989 t == TypeManager.int64_type ||
1990 t == TypeManager.uint64_type)
1992 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1994 TypeCode tc = Type.GetTypeCode (t);
1997 case TypeCode.Boolean:
1998 return TypeManager.bool_type;
2000 return TypeManager.byte_type;
2001 case TypeCode.SByte:
2002 return TypeManager.sbyte_type;
2004 return TypeManager.char_type;
2005 case TypeCode.Int16:
2006 return TypeManager.short_type;
2007 case TypeCode.UInt16:
2008 return TypeManager.ushort_type;
2009 case TypeCode.Int32:
2010 return TypeManager.int32_type;
2011 case TypeCode.UInt32:
2012 return TypeManager.uint32_type;
2013 case TypeCode.Int64:
2014 return TypeManager.int64_type;
2015 case TypeCode.UInt64:
2016 return TypeManager.uint64_type;
2018 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2022 // When compiling corlib and called with one of the core types, return
2023 // the corresponding typebuilder for that type.
2025 public static Type TypeToCoreType (Type t)
2027 if (RootContext.StdLib || (t is TypeBuilder))
2030 TypeCode tc = Type.GetTypeCode (t);
2033 case TypeCode.Boolean:
2034 return TypeManager.bool_type;
2036 return TypeManager.byte_type;
2037 case TypeCode.SByte:
2038 return TypeManager.sbyte_type;
2040 return TypeManager.char_type;
2041 case TypeCode.Int16:
2042 return TypeManager.short_type;
2043 case TypeCode.UInt16:
2044 return TypeManager.ushort_type;
2045 case TypeCode.Int32:
2046 return TypeManager.int32_type;
2047 case TypeCode.UInt32:
2048 return TypeManager.uint32_type;
2049 case TypeCode.Int64:
2050 return TypeManager.int64_type;
2051 case TypeCode.UInt64:
2052 return TypeManager.uint64_type;
2053 case TypeCode.Single:
2054 return TypeManager.float_type;
2055 case TypeCode.Double:
2056 return TypeManager.double_type;
2057 case TypeCode.String:
2058 return TypeManager.string_type;
2060 if (t == typeof (void))
2061 return TypeManager.void_type;
2062 if (t == typeof (object))
2063 return TypeManager.object_type;
2064 if (t == typeof (System.Type))
2065 return TypeManager.type_type;
2071 /// Utility function that can be used to probe whether a type
2072 /// is managed or not.
2074 public static bool VerifyUnManaged (Type t, Location loc)
2076 if (t.IsValueType || t.IsPointer){
2078 // FIXME: this is more complex, we actually need to
2079 // make sure that the type does not contain any
2085 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2086 // We need this explicit check here to make it work when
2087 // compiling corlib.
2092 "Cannot take the address or size of a variable of a managed type ('" +
2093 CSharpName (t) + "')");
2098 /// Returns the name of the indexer in a given type.
2101 /// The default is not always `Item'. The user can change this behaviour by
2102 /// using the DefaultMemberAttribute in the class.
2104 /// For example, the String class indexer is named `Chars' not `Item'
2106 public static string IndexerPropertyName (Type t)
2108 if (t is TypeBuilder) {
2109 if (t.IsInterface) {
2110 Interface i = LookupInterface (t);
2112 if ((i == null) || (i.IndexerName == null))
2115 return i.IndexerName;
2117 TypeContainer tc = LookupTypeContainer (t);
2119 if ((tc == null) || (tc.IndexerName == null))
2122 return tc.IndexerName;
2126 System.Attribute attr = System.Attribute.GetCustomAttribute (
2127 t, TypeManager.default_member_type);
2129 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2130 return dma.MemberName;
2136 public static void MakePinned (LocalBuilder builder)
2139 // FIXME: Flag the "LocalBuilder" type as being
2140 // pinned. Figure out API.
2146 // Returns whether the array of memberinfos contains the given method
2148 public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2150 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2152 foreach (MethodBase method in array) {
2153 if (method.Name != new_method.Name)
2156 if (method is MethodInfo && new_method is MethodInfo)
2157 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2161 Type [] old_args = TypeManager.GetArgumentTypes (method);
2162 int old_count = old_args.Length;
2165 if (new_args.Length != old_count)
2168 for (i = 0; i < old_count; i++){
2169 if (old_args [i] != new_args [i])
2182 // We copy methods from `new_members' into `target_list' if the signature
2183 // for the method from in the new list does not exist in the target_list
2185 // The name is assumed to be the same.
2187 public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
2189 if (target_list == null){
2190 target_list = new ArrayList ();
2192 foreach (MemberInfo mi in new_members){
2193 if (mi is MethodBase)
2194 target_list.Add (mi);
2199 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2200 target_list.CopyTo (target_array, 0);
2202 foreach (MemberInfo mi in new_members){
2203 MethodBase new_method = (MethodBase) mi;
2205 if (!ArrayContainsMethod (target_array, new_method))
2206 target_list.Add (new_method);
2212 public enum MethodFlags {
2214 IsObsoleteError = 1 << 1,
2215 ShouldIgnore = 1 << 2
2219 // Returns the TypeManager.MethodFlags for this method.
2220 // This emits an error 619 / warning 618 if the method is obsolete.
2221 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2223 static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2225 MethodFlags flags = 0;
2227 if (mb.DeclaringType is TypeBuilder){
2228 MethodData method = (MethodData) builder_to_method [mb];
2229 if (method == null) {
2230 // FIXME: implement Obsolete attribute on Property,
2231 // Indexer and Event.
2235 return method.GetMethodFlags (loc);
2238 object [] attrs = mb.GetCustomAttributes (true);
2239 foreach (object ta in attrs){
2240 if (!(ta is System.Attribute)){
2241 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2244 System.Attribute a = (System.Attribute) ta;
2245 if (a.TypeId == TypeManager.obsolete_attribute_type){
2246 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2248 string method_desc = TypeManager.CSharpSignature (mb);
2251 Report.Error (619, loc, "Method `" + method_desc +
2252 "' is obsolete: `" + oa.Message + "'");
2253 return MethodFlags.IsObsoleteError;
2255 Report.Warning (618, loc, "Method `" + method_desc +
2256 "' is obsolete: `" + oa.Message + "'");
2258 flags |= MethodFlags.IsObsolete;
2264 // Skip over conditional code.
2266 if (a.TypeId == TypeManager.conditional_attribute_type){
2267 ConditionalAttribute ca = (ConditionalAttribute) a;
2269 if (RootContext.AllDefines [ca.ConditionString] == null)
2270 flags |= MethodFlags.ShouldIgnore;
2277 #region MemberLookup implementation
2280 // Whether we allow private members in the result (since FindMembers
2281 // uses NonPublic for both protected and private), we need to distinguish.
2283 static bool closure_private_ok;
2286 // Who is invoking us and which type is being queried currently.
2288 static Type closure_invocation_type;
2289 static Type closure_qualifier_type;
2292 // The assembly that defines the type is that is calling us
2294 static Assembly closure_invocation_assembly;
2296 static internal bool FilterNone (MemberInfo m, object filter_criteria)
2302 // This filter filters by name + whether it is ok to include private
2303 // members in the search
2305 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2308 // Hack: we know that the filter criteria will always be in the `closure'
2312 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2315 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2316 (m.DeclaringType == closure_invocation_type))
2320 // Ugly: we need to find out the type of `m', and depending
2321 // on this, tell whether we accept or not
2323 if (m is MethodBase){
2324 MethodBase mb = (MethodBase) m;
2325 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2327 if (ma == MethodAttributes.Private)
2328 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2329 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2332 // FamAndAssem requires that we not only derivate, but we are on the
2335 if (ma == MethodAttributes.FamANDAssem){
2336 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2340 // Assembly and FamORAssem succeed if we're in the same assembly.
2341 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2342 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2346 // We already know that we aren't in the same assembly.
2347 if (ma == MethodAttributes.Assembly)
2350 // Family and FamANDAssem require that we derive.
2351 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2352 if (closure_invocation_type == null)
2355 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2358 // Although a derived class can access protected members of its base class
2359 // it cannot do so through an instance of the base class (CS1540).
2360 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2361 (closure_qualifier_type != null) &&
2362 closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2372 if (m is FieldInfo){
2373 FieldInfo fi = (FieldInfo) m;
2374 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2376 if (fa == FieldAttributes.Private)
2377 return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
2378 IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2381 // FamAndAssem requires that we not only derivate, but we are on the
2384 if (fa == FieldAttributes.FamANDAssem){
2385 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2389 // Assembly and FamORAssem succeed if we're in the same assembly.
2390 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2391 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2395 // We already know that we aren't in the same assembly.
2396 if (fa == FieldAttributes.Assembly)
2399 // Family and FamANDAssem require that we derive.
2400 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2401 if (closure_invocation_type == null)
2404 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2407 // Although a derived class can access protected members of its base class
2408 // it cannot do so through an instance of the base class (CS1540).
2409 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2410 (closure_qualifier_type != null) &&
2411 closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2422 // EventInfos and PropertyInfos, return true because they lack permission
2423 // informaiton, so we need to check later on the methods.
2428 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2429 static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2432 // Looks up a member called `name' in the `queried_type'. This lookup
2433 // is done by code that is contained in the definition for `invocation_type'
2434 // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2436 // `invocation_type' is used to check whether we're allowed to access the requested
2437 // member wrt its protection level.
2439 // When called from MemberAccess, `qualifier_type' is the type which is used to access
2440 // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2441 // is B and qualifier_type is A). This is used to do the CS1540 check.
2443 // When resolving a SimpleName, `qualifier_type' is null.
2445 // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2446 // the same than `queried_type' - except when we're being called from BaseAccess;
2447 // in this case, `invocation_type' is the current type and `queried_type' the base
2448 // type, so this'd normally trigger a CS1540.
2450 // The binding flags are `bf' and the kind of members being looked up are `mt'
2452 // The return value always includes private members which code in `invocation_type'
2453 // is allowed to access (using the specified `qualifier_type' if given); only use
2454 // BindingFlags.NonPublic to bypass the permission check.
2456 // Returns an array of a single element for everything but Methods/Constructors
2457 // that might return multiple matches.
2459 public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2460 Type queried_type, MemberTypes mt,
2461 BindingFlags original_bf, string name)
2463 Timer.StartTimer (TimerType.MemberLookup);
2465 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2466 queried_type, mt, original_bf, name);
2468 Timer.StopTimer (TimerType.MemberLookup);
2473 static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2474 Type queried_type, MemberTypes mt,
2475 BindingFlags original_bf, string name)
2477 BindingFlags bf = original_bf;
2479 ArrayList method_list = null;
2480 Type current_type = queried_type;
2481 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2482 bool skip_iface_check = true, used_cache = false;
2483 bool always_ok_flag = false;
2485 closure_invocation_type = invocation_type;
2486 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2487 closure_qualifier_type = qualifier_type;
2490 // If we are a nested class, we always have access to our container
2493 if (invocation_type != null){
2494 string invocation_name = invocation_type.FullName;
2495 if (invocation_name.IndexOf ('+') != -1){
2496 string container = queried_type.FullName + "+";
2497 int container_length = container.Length;
2499 if (invocation_name.Length > container_length){
2500 string shared = invocation_name.Substring (0, container_length);
2502 if (shared == container)
2503 always_ok_flag = true;
2512 // `NonPublic' is lame, because it includes both protected and
2513 // private methods, so we need to control this behavior by
2514 // explicitly tracking if a private method is ok or not.
2516 // The possible cases are:
2517 // public, private and protected (internal does not come into the
2520 if ((invocation_type != null) &&
2521 ((invocation_type == current_type) ||
2522 IsNestedChildOf (invocation_type, current_type)) ||
2524 bf = original_bf | BindingFlags.NonPublic;
2528 closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2530 Timer.StopTimer (TimerType.MemberLookup);
2532 list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2534 Timer.StartTimer (TimerType.MemberLookup);
2537 // When queried for an interface type, the cache will automatically check all
2538 // inherited members, so we don't need to do this here. However, this only
2539 // works if we already used the cache in the first iteration of this loop.
2541 // If we used the cache in any further iteration, we can still terminate the
2542 // loop since the cache always looks in all parent classes.
2548 skip_iface_check = false;
2550 if (current_type == TypeManager.object_type)
2553 current_type = current_type.BaseType;
2556 // This happens with interfaces, they have a null
2557 // basetype. Look members up in the Object class.
2559 if (current_type == null)
2560 current_type = TypeManager.object_type;
2563 if (list.Count == 0)
2567 // Events and types are returned by both `static' and `instance'
2568 // searches, which means that our above FindMembers will
2569 // return two copies of the same.
2571 if (list.Count == 1 && !(list [0] is MethodBase)){
2572 return (MemberInfo []) list;
2576 // Multiple properties: we query those just to find out the indexer
2579 if (list [0] is PropertyInfo)
2580 return (MemberInfo []) list;
2583 // We found an event: the cache lookup returns both the event and
2584 // its private field.
2586 if (list [0] is EventInfo) {
2587 if ((list.Count == 2) && (list [1] is FieldInfo))
2588 return new MemberInfo [] { list [0] };
2595 // We found methods, turn the search into "method scan"
2599 method_list = CopyNewMethods (method_list, list);
2600 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2601 } while (searching);
2603 if (method_list != null && method_list.Count > 0)
2604 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2607 // This happens if we already used the cache in the first iteration, in this case
2608 // the cache already looked in all interfaces.
2610 if (skip_iface_check)
2614 // Interfaces do not list members they inherit, so we have to
2617 if (!queried_type.IsInterface)
2620 if (queried_type.IsArray)
2621 queried_type = TypeManager.array_type;
2623 TypeExpr [] ifaces = GetInterfaces (queried_type);
2627 foreach (TypeExpr itype in ifaces){
2630 x = MemberLookup (null, null, itype.Type, mt, bf, name);
2639 // This is used to extract properties and event declarations from a type
2641 static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2643 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2645 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2647 if (t is TypeBuilder) {
2648 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2650 return (MemberInfo []) decl.FindMembers (
2651 MemberTypes.Property | MemberTypes.Event,
2652 bf, FilterNone_delegate, null);
2654 return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2655 bf, FilterNone_delegate, null);
2660 public static bool IsSpecialMethod (MethodBase mb)
2662 Type t = mb.DeclaringType;
2664 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2665 if (matches == null)
2668 foreach (MemberInfo mi in matches){
2669 if (mi is PropertyBuilder){
2670 Pair p = (Pair) properties [mi];
2672 if (p.First == mb || p.Second == mb)
2674 } else if (mi is PropertyInfo){
2675 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2677 foreach (MethodInfo m in methods){
2681 } else if (mi is MyEventBuilder){
2682 Pair p = (Pair) events [mi];
2684 if (p.First == mb || p.Second == mb)
2686 } else if (mi is EventInfo){
2687 EventInfo ei = ((EventInfo) mi);
2689 if (ei.GetAddMethod (true) == mb)
2692 if (ei.GetRemoveMethod (true) == mb)
2695 if (ei.GetRaiseMethod (true) == mb)
2701 // Now check if it is an operator method
2705 if (s.StartsWith ("op_")){
2706 foreach (string name in Unary.oper_names){
2711 foreach (string name in Binary.oper_names){
2725 /// There is exactly one instance of this class per type.
2727 public sealed class TypeHandle : IMemberContainer {
2728 public readonly TypeHandle BaseType;
2730 readonly int id = ++next_id;
2731 static int next_id = 0;
2734 /// Lookup a TypeHandle instance for the given type. If the type doesn't have
2735 /// a TypeHandle yet, a new instance of it is created. This static method
2736 /// ensures that we'll only have one TypeHandle instance per type.
2738 public static TypeHandle GetTypeHandle (Type t)
2740 TypeHandle handle = (TypeHandle) type_hash [t];
2744 handle = new TypeHandle (t);
2745 type_hash.Add (t, handle);
2749 public static void CleanUp ()
2755 /// Returns the TypeHandle for TypeManager.object_type.
2757 public static IMemberContainer ObjectType {
2759 if (object_type != null)
2762 object_type = GetTypeHandle (TypeManager.object_type);
2769 /// Returns the TypeHandle for TypeManager.array_type.
2771 public static IMemberContainer ArrayType {
2773 if (array_type != null)
2776 array_type = GetTypeHandle (TypeManager.array_type);
2782 private static PtrHashtable type_hash = new PtrHashtable ();
2784 private static TypeHandle object_type = null;
2785 private static TypeHandle array_type = null;
2788 private bool is_interface;
2789 private MemberCache member_cache;
2791 private TypeHandle (Type type)
2794 if (type.BaseType != null)
2795 BaseType = GetTypeHandle (type.BaseType);
2796 this.is_interface = type.IsInterface;
2797 this.member_cache = new MemberCache (this);
2800 // IMemberContainer methods
2802 public string Name {
2804 return type.FullName;
2814 public IMemberContainer Parent {
2820 public bool IsInterface {
2822 return is_interface;
2826 public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2828 MemberInfo [] members;
2829 if (mt == MemberTypes.Event)
2830 members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2832 members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2834 Array.Reverse (members);
2836 return new MemberList (members);
2839 // IMemberFinder methods
2841 public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2842 MemberFilter filter, object criteria)
2844 return member_cache.FindMembers (mt, bf, name, filter, criteria);
2847 public MemberCache MemberCache {
2849 return member_cache;
2853 public override string ToString ()
2855 if (BaseType != null)
2856 return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2858 return "TypeHandle (" + id + "," + Name + ")";