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)
15 using System.Globalization;
16 using System.Collections;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Text.RegularExpressions;
20 using System.Runtime.CompilerServices;
21 using System.Diagnostics;
23 namespace Mono.CSharp {
25 public class TypeManager {
27 // A list of core types that the compiler requires or uses
29 static public Type object_type;
30 static public Type value_type;
31 static public Type string_type;
32 static public Type int32_type;
33 static public Type uint32_type;
34 static public Type int64_type;
35 static public Type uint64_type;
36 static public Type float_type;
37 static public Type double_type;
38 static public Type char_type;
39 static public Type char_ptr_type;
40 static public Type short_type;
41 static public Type decimal_type;
42 static public Type bool_type;
43 static public Type sbyte_type;
44 static public Type byte_type;
45 static public Type ushort_type;
46 static public Type enum_type;
47 static public Type delegate_type;
48 static public Type multicast_delegate_type;
49 static public Type void_type;
50 static public Type enumeration_type;
51 static public Type array_type;
52 static public Type runtime_handle_type;
53 static public Type icloneable_type;
54 static public Type type_type;
55 static public Type ienumerator_type;
56 static public Type idisposable_type;
57 static public Type default_member_type;
58 static public Type iasyncresult_type;
59 static public Type asynccallback_type;
60 static public Type intptr_type;
61 static public Type monitor_type;
62 static public Type runtime_field_handle_type;
63 static public Type attribute_type;
64 static public Type attribute_usage_type;
65 static public Type dllimport_type;
66 static public Type unverifiable_code_type;
67 static public Type methodimpl_attr_type;
68 static public Type marshal_as_attr_type;
69 static public Type param_array_type;
70 static public Type void_ptr_type;
71 static public Type indexer_name_type;
72 static public Type exception_type;
73 static public object obsolete_attribute_type;
74 static public object conditional_attribute_type;
77 // An empty array of types
79 static public Type [] NoTypes;
83 // Expressions representing the internal types. Used during declaration
86 static public Expression system_object_expr, system_string_expr;
87 static public Expression system_boolean_expr, system_decimal_expr;
88 static public Expression system_single_expr, system_double_expr;
89 static public Expression system_sbyte_expr, system_byte_expr;
90 static public Expression system_int16_expr, system_uint16_expr;
91 static public Expression system_int32_expr, system_uint32_expr;
92 static public Expression system_int64_expr, system_uint64_expr;
93 static public Expression system_char_expr, system_void_expr;
94 static public Expression system_asynccallback_expr;
95 static public Expression system_iasyncresult_expr;
98 // This is only used when compiling corlib
100 static public Type system_int32_type;
101 static public Type system_array_type;
102 static public Type system_type_type;
103 static public Type system_assemblybuilder_type;
104 static public MethodInfo system_int_array_get_length;
105 static public MethodInfo system_int_array_get_rank;
106 static public MethodInfo system_object_array_clone;
107 static public MethodInfo system_int_array_get_length_int;
108 static public MethodInfo system_int_array_get_lower_bound_int;
109 static public MethodInfo system_int_array_get_upper_bound_int;
110 static public MethodInfo system_void_array_copyto_array_int;
111 static public MethodInfo system_void_set_corlib_type_builders;
115 // Internal, not really used outside
117 static Type runtime_helpers_type;
120 // These methods are called by code generated by the compiler
122 static public MethodInfo string_concat_string_string;
123 static public MethodInfo string_concat_object_object;
124 static public MethodInfo string_isinterneted_string;
125 static public MethodInfo system_type_get_type_from_handle;
126 static public MethodInfo object_getcurrent_void;
127 static public MethodInfo bool_movenext_void;
128 static public MethodInfo void_dispose_void;
129 static public MethodInfo void_monitor_enter_object;
130 static public MethodInfo void_monitor_exit_object;
131 static public MethodInfo void_initializearray_array_fieldhandle;
132 static public MethodInfo int_getlength_int;
133 static public MethodInfo delegate_combine_delegate_delegate;
134 static public MethodInfo delegate_remove_delegate_delegate;
135 static public MethodInfo int_get_offset_to_string_data;
136 static public MethodInfo int_array_get_length;
137 static public MethodInfo int_array_get_rank;
138 static public MethodInfo object_array_clone;
139 static public MethodInfo int_array_get_length_int;
140 static public MethodInfo int_array_get_lower_bound_int;
141 static public MethodInfo int_array_get_upper_bound_int;
142 static public MethodInfo void_array_copyto_array_int;
145 // The attribute constructors.
147 static public ConstructorInfo cons_param_array_attribute;
148 static public ConstructorInfo void_decimal_ctor_five_args;
149 static public ConstructorInfo unverifiable_code_ctor;
152 // Holds the Array of Assemblies that have been loaded
153 // (either because it is the default or the user used the
154 // -r command line option)
156 static Assembly [] assemblies;
159 // Keeps a list of module builders. We used this to do lookups
160 // on the modulebuilder using GetType -- needed for arrays
162 static ModuleBuilder [] modules;
165 // This is the type_cache from the assemblies to avoid
166 // hitting System.Reflection on every lookup.
168 static Hashtable types;
171 // This is used to hotld the corresponding TypeContainer objects
172 // since we need this in FindMembers
174 static Hashtable typecontainers;
177 // Keeps track of those types that are defined by the
180 static ArrayList user_types;
183 // Keeps a mapping between TypeBuilders and their TypeContainers
185 static PtrHashtable builder_to_container;
188 // Tracks the interfaces implemented by typebuilders. We only
189 // enter those who do implement or or more interfaces
191 static PtrHashtable builder_to_ifaces;
194 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
195 // the arguments to the method
197 static Hashtable method_arguments;
200 // Maps PropertyBuilder to a Type array that contains
201 // the arguments to the indexer
203 static Hashtable indexer_arguments;
206 // Maybe `method_arguments' should be replaced and only
207 // method_internal_params should be kept?
209 static Hashtable method_internal_params;
211 static PtrHashtable builder_to_interface;
214 // Keeps track of delegate types
217 static Hashtable builder_to_delegate;
220 // Keeps track of enum types
223 static Hashtable builder_to_enum;
226 // Keeps track of attribute types
229 static Hashtable builder_to_attr;
232 // Keeps track of methods
235 static Hashtable builder_to_method;
243 /// A filter for Findmembers that uses the Signature object to
246 static bool SignatureFilter (MemberInfo mi, object criteria)
248 Signature sig = (Signature) criteria;
250 if (!(mi is MethodBase))
253 if (mi.Name != sig.name)
256 int count = sig.args.Length;
258 if (mi is MethodBuilder || mi is ConstructorBuilder){
259 Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
261 if (candidate_args.Length != count)
264 for (int i = 0; i < count; i++)
265 if (candidate_args [i] != sig.args [i])
270 ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
272 if (pars.Length != count)
275 for (int i = 0; i < count; i++)
276 if (pars [i].ParameterType != sig.args [i])
282 // A delegate that points to the filter above.
283 static MemberFilter signature_filter;
286 // These are expressions that represent some of the internal data types, used
289 static void InitExpressionTypes ()
291 system_object_expr = new TypeExpression ("System.Object");
292 system_string_expr = new TypeExpression ("System.String");
293 system_boolean_expr = new TypeExpression ("System.Boolean");
294 system_decimal_expr = new TypeExpression ("System.Decimal");
295 system_single_expr = new TypeExpression ("System.Single");
296 system_double_expr = new TypeExpression ("System.Double");
297 system_sbyte_expr = new TypeExpression ("System.SByte");
298 system_byte_expr = new TypeExpression ("System.Byte");
299 system_int16_expr = new TypeExpression ("System.Int16");
300 system_uint16_expr = new TypeExpression ("System.UInt16");
301 system_int32_expr = new TypeExpression ("System.Int32");
302 system_uint32_expr = new TypeExpression ("System.UInt32");
303 system_int64_expr = new TypeExpression ("System.Int64");
304 system_uint64_expr = new TypeExpression ("System.UInt64");
305 system_char_expr = new TypeExpression ("System.Char");
306 system_void_expr = new TypeExpression ("System.Void");
307 system_asynccallback_expr = new TypeExpression ("System.AsyncCallback");
308 system_iasyncresult_expr = new TypeExpression ("System.IAsyncResult");
311 static TypeManager ()
313 assemblies = new Assembly [0];
315 user_types = new ArrayList ();
317 types = new Hashtable ();
318 typecontainers = new Hashtable ();
320 builder_to_interface = new PtrHashtable ();
321 builder_to_delegate = new PtrHashtable ();
322 builder_to_enum = new PtrHashtable ();
323 builder_to_attr = new PtrHashtable ();
324 builder_to_method = new PtrHashtable ();
325 method_arguments = new PtrHashtable ();
326 method_internal_params = new PtrHashtable ();
327 indexer_arguments = new PtrHashtable ();
328 builder_to_container = new PtrHashtable ();
329 builder_to_ifaces = new PtrHashtable ();
331 NoTypes = new Type [0];
333 signature_filter = new MemberFilter (SignatureFilter);
334 InitExpressionTypes ();
337 public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
342 Type prev = (Type) types [name];
343 TypeContainer tc = (TypeContainer) builder_to_container [prev];
347 // This probably never happens, as we catch this before
349 Report.Error (-17, "The type `" + name + "' has already been defined.");
353 tc = (TypeContainer) builder_to_container [t];
356 1595, "The type `" + name + "' is defined in an existing assembly;"+
357 " Using the new definition from: " + tc.Location);
358 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
366 builder_to_ifaces [t] = ifaces;
370 // This entry point is used by types that we define under the covers
372 public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
375 builder_to_ifaces [tb] = ifaces;
378 public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
380 builder_to_container.Add (t, tc);
381 typecontainers.Add (name, tc);
382 AddUserType (name, t, ifaces);
385 public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
388 builder_to_delegate.Add (t, del);
391 public static void AddEnumType (string name, TypeBuilder t, Enum en)
394 builder_to_enum.Add (t, en);
397 public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
399 AddUserType (name, t, ifaces);
400 builder_to_interface.Add (t, i);
403 public static void AddMethod (MethodBuilder builder, MethodData method)
405 builder_to_method.Add (builder, method);
408 public static void RegisterAttrType (Type t, TypeContainer tc)
410 builder_to_attr.Add (t, tc);
414 /// Returns the TypeContainer whose Type is `t' or null if there is no
415 /// TypeContainer for `t' (ie, the Type comes from a library)
417 public static TypeContainer LookupTypeContainer (Type t)
419 return (TypeContainer) builder_to_container [t];
422 public static Interface LookupInterface (Type t)
424 return (Interface) builder_to_interface [t];
427 public static Delegate LookupDelegate (Type t)
429 return (Delegate) builder_to_delegate [t];
432 public static Enum LookupEnum (Type t)
434 return (Enum) builder_to_enum [t];
437 public static TypeContainer LookupAttr (Type t)
439 return (TypeContainer) builder_to_attr [t];
443 /// Registers an assembly to load types from.
445 public static void AddAssembly (Assembly a)
447 int top = assemblies.Length;
448 Assembly [] n = new Assembly [top + 1];
450 assemblies.CopyTo (n, 0);
457 /// Registers a module builder to lookup types from
459 public static void AddModule (ModuleBuilder mb)
461 int top = modules != null ? modules.Length : 0;
462 ModuleBuilder [] n = new ModuleBuilder [top + 1];
465 modules.CopyTo (n, 0);
471 /// Returns the Type associated with @name
473 public static Type LookupType (string name)
478 // First lookup in user defined and cached values
481 t = (Type) types [name];
485 foreach (Assembly a in assemblies){
486 t = a.GetType (name);
494 foreach (ModuleBuilder mb in modules) {
495 t = mb.GetType (name);
506 /// Returns the C# name of a type if possible, or the full type name otherwise
508 static public string CSharpName (Type t)
510 return Regex.Replace (t.FullName,
512 @"(Int32|UInt32|Int16|Uint16|Int64|UInt64|" +
513 @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
514 @"Boolean|String|Void)" +
516 new MatchEvaluator (CSharpNameMatch));
519 static String CSharpNameMatch (Match match)
521 string s = match.Groups [1].Captures [0].Value;
523 Replace ("int32", "int").
524 Replace ("uint32", "uint").
525 Replace ("int16", "short").
526 Replace ("uint16", "ushort").
527 Replace ("int64", "long").
528 Replace ("uint64", "ulong").
529 Replace ("single", "float").
530 Replace ("boolean", "bool")
531 + match.Groups [2].Captures [0].Value;
535 /// Returns the signature of the method
537 static public string CSharpSignature (MethodBase mb)
542 // FIXME: We should really have a single function to do
543 // everything instead of the following 5 line pattern
545 ParameterData iparams = LookupParametersByBuilder (mb);
547 if (iparams == null){
548 ParameterInfo [] pi = mb.GetParameters ();
549 iparams = new ReflectionParameters (pi);
552 for (int i = 0; i < iparams.Count; i++) {
556 sig += iparams.ParameterDesc(i);
560 return mb.DeclaringType.Name + "." + mb.Name + sig;
564 /// Looks up a type, and aborts if it is not found. This is used
565 /// by types required by the compiler
567 static Type CoreLookupType (string name)
569 Type t = LookupType (name);
572 Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
573 Environment.Exit (0);
580 /// Returns the MethodInfo for a method named `name' defined
581 /// in type `t' which takes arguments of types `args'
583 static MethodInfo GetMethod (Type t, string name, Type [] args)
592 t, MemberTypes.Method,
593 instance_and_static | BindingFlags.Public, signature_filter, sig);
594 if (mi == null || mi.Length == 0 || !(mi [0] is MethodInfo)){
595 Report.Error (-19, "Can not find the core function `" + name + "'");
599 return (MethodInfo) mi [0];
603 /// Returns the ConstructorInfo for "args"
605 static ConstructorInfo GetConstructor (Type t, Type [] args)
613 mi = FindMembers (t, MemberTypes.Constructor,
614 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly, signature_filter, sig);
615 if (mi == null || mi.Length == 0 || !(mi [0] is ConstructorInfo)){
616 Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
620 return (ConstructorInfo) mi [0];
623 public static void InitEnumUnderlyingTypes ()
626 int32_type = CoreLookupType ("System.Int32");
627 int64_type = CoreLookupType ("System.Int64");
628 uint32_type = CoreLookupType ("System.UInt32");
629 uint64_type = CoreLookupType ("System.UInt64");
630 byte_type = CoreLookupType ("System.Byte");
631 sbyte_type = CoreLookupType ("System.SByte");
632 short_type = CoreLookupType ("System.Int16");
633 ushort_type = CoreLookupType ("System.UInt16");
637 /// The types have to be initialized after the initial
638 /// population of the type has happened (for example, to
639 /// bootstrap the corlib.dll
641 public static void InitCoreTypes ()
643 object_type = CoreLookupType ("System.Object");
644 value_type = CoreLookupType ("System.ValueType");
646 InitEnumUnderlyingTypes ();
648 char_type = CoreLookupType ("System.Char");
649 string_type = CoreLookupType ("System.String");
650 float_type = CoreLookupType ("System.Single");
651 double_type = CoreLookupType ("System.Double");
652 char_ptr_type = CoreLookupType ("System.Char*");
653 decimal_type = CoreLookupType ("System.Decimal");
654 bool_type = CoreLookupType ("System.Boolean");
655 enum_type = CoreLookupType ("System.Enum");
657 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
658 delegate_type = CoreLookupType ("System.Delegate");
660 array_type = CoreLookupType ("System.Array");
661 void_type = CoreLookupType ("System.Void");
662 type_type = CoreLookupType ("System.Type");
664 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
665 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
666 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
667 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
668 asynccallback_type = CoreLookupType ("System.AsyncCallback");
669 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
670 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
671 idisposable_type = CoreLookupType ("System.IDisposable");
672 icloneable_type = CoreLookupType ("System.ICloneable");
673 monitor_type = CoreLookupType ("System.Threading.Monitor");
674 intptr_type = CoreLookupType ("System.IntPtr");
676 attribute_type = CoreLookupType ("System.Attribute");
677 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
678 dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
679 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
680 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
681 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
683 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
685 void_ptr_type = CoreLookupType ("System.Void*");
687 indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
689 exception_type = CoreLookupType ("System.Exception");
694 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
695 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
698 // When compiling corlib, store the "real" types here.
700 if (!RootContext.StdLib) {
701 system_int32_type = typeof (System.Int32);
702 system_array_type = typeof (System.Array);
703 system_type_type = typeof (System.Type);
704 system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
706 Type [] void_arg = { };
707 system_int_array_get_length = GetMethod (
708 system_array_type, "get_Length", void_arg);
709 system_int_array_get_rank = GetMethod (
710 system_array_type, "get_Rank", void_arg);
711 system_object_array_clone = GetMethod (
712 system_array_type, "Clone", void_arg);
714 Type [] system_int_arg = { system_int32_type };
715 system_int_array_get_length_int = GetMethod (
716 system_array_type, "GetLength", system_int_arg);
717 system_int_array_get_upper_bound_int = GetMethod (
718 system_array_type, "GetUpperBound", system_int_arg);
719 system_int_array_get_lower_bound_int = GetMethod (
720 system_array_type, "GetLowerBound", system_int_arg);
722 Type [] system_array_int_arg = { system_array_type, system_int32_type };
723 system_void_array_copyto_array_int = GetMethod (
724 system_array_type, "CopyTo", system_array_int_arg);
726 Type [] system_type_type_arg = { system_type_type, system_type_type, system_type_type };
729 system_void_set_corlib_type_builders = GetMethod (
730 system_assemblybuilder_type, "SetCorlibTypeBuilders",
731 system_type_type_arg);
733 object[] args = new object [3];
734 args [0] = object_type;
735 args [1] = value_type;
736 args [2] = enum_type;
738 system_void_set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
740 Console.WriteLine ("Corlib compilation is not supported in Microsoft.NET due to bugs in it");
746 // The helper methods that are used by the compiler
748 public static void InitCodeHelpers ()
751 // Now load the default methods that we use.
753 Type [] string_string = { string_type, string_type };
754 string_concat_string_string = GetMethod (
755 string_type, "Concat", string_string);
757 Type [] object_object = { object_type, object_type };
758 string_concat_object_object = GetMethod (
759 string_type, "Concat", object_object);
761 Type [] string_ = { string_type };
762 string_isinterneted_string = GetMethod (
763 string_type, "IsInterned", string_);
765 Type [] runtime_type_handle = { runtime_handle_type };
766 system_type_get_type_from_handle = GetMethod (
767 type_type, "GetTypeFromHandle", runtime_type_handle);
769 Type [] delegate_delegate = { delegate_type, delegate_type };
770 delegate_combine_delegate_delegate = GetMethod (
771 delegate_type, "Combine", delegate_delegate);
773 delegate_remove_delegate_delegate = GetMethod (
774 delegate_type, "Remove", delegate_delegate);
779 Type [] void_arg = { };
780 object_getcurrent_void = GetMethod (
781 ienumerator_type, "get_Current", void_arg);
782 bool_movenext_void = GetMethod (
783 ienumerator_type, "MoveNext", void_arg);
784 void_dispose_void = GetMethod (
785 idisposable_type, "Dispose", void_arg);
786 int_get_offset_to_string_data = GetMethod (
787 runtime_helpers_type, "get_OffsetToStringData", void_arg);
788 int_array_get_length = GetMethod (
789 array_type, "get_Length", void_arg);
790 int_array_get_rank = GetMethod (
791 array_type, "get_Rank", void_arg);
796 Type [] int_arg = { int32_type };
797 int_array_get_length_int = GetMethod (
798 array_type, "GetLength", int_arg);
799 int_array_get_upper_bound_int = GetMethod (
800 array_type, "GetUpperBound", int_arg);
801 int_array_get_lower_bound_int = GetMethod (
802 array_type, "GetLowerBound", int_arg);
805 // System.Array methods
807 object_array_clone = GetMethod (
808 array_type, "Clone", void_arg);
809 Type [] array_int_arg = { array_type, int32_type };
810 void_array_copyto_array_int = GetMethod (
811 array_type, "CopyTo", array_int_arg);
816 Type [] object_arg = { object_type };
817 void_monitor_enter_object = GetMethod (
818 monitor_type, "Enter", object_arg);
819 void_monitor_exit_object = GetMethod (
820 monitor_type, "Exit", object_arg);
822 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
824 void_initializearray_array_fieldhandle = GetMethod (
825 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
830 int_getlength_int = GetMethod (
831 array_type, "GetLength", int_arg);
834 // Decimal constructors
836 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
837 void_decimal_ctor_five_args = GetConstructor (
838 decimal_type, dec_arg);
843 cons_param_array_attribute = GetConstructor (
844 param_array_type, void_arg);
846 unverifiable_code_ctor = GetConstructor (
847 unverifiable_code_type, void_arg);
851 const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
854 // FIXME: This can be optimized easily. speedup by having a single builder mapping
856 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
857 MemberFilter filter, object criteria)
860 // We have to take care of arrays specially, because GetType on
861 // a TypeBuilder array will return a Type, not a TypeBuilder,
862 // and we can not call FindMembers on this type.
864 if (t.IsSubclassOf (TypeManager.array_type))
865 return TypeManager.array_type.FindMembers (mt, bf, filter, criteria);
867 if (!(t is TypeBuilder)){
869 // Since FindMembers will not lookup both static and instance
870 // members, we emulate this behaviour here.
872 if ((bf & instance_and_static) == instance_and_static){
873 MemberInfo [] i_members = t.FindMembers (
874 mt, bf & ~BindingFlags.Static, filter, criteria);
876 int i_len = i_members.Length;
878 MemberInfo one = i_members [0];
881 // If any of these are present, we are done!
883 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
887 MemberInfo [] s_members = t.FindMembers (
888 mt, bf & ~BindingFlags.Instance, filter, criteria);
890 int s_len = s_members.Length;
891 if (i_len > 0 || s_len > 0){
892 MemberInfo [] both = new MemberInfo [i_len + s_len];
894 i_members.CopyTo (both, 0);
895 s_members.CopyTo (both, i_len);
905 return t.FindMembers (mt, bf, filter, criteria);
909 // FIXME: We should not have builder_to_blah everywhere,
910 // we should just have a builder_to_findmemberizable
911 // and have them implement a new ICanFindMembers interface
913 Enum e = (Enum) builder_to_enum [t];
916 return e.FindMembers (mt, bf, filter, criteria);
918 Delegate del = (Delegate) builder_to_delegate [t];
921 return del.FindMembers (mt, bf, filter, criteria);
923 Interface iface = (Interface) builder_to_interface [t];
926 return iface.FindMembers (mt, bf, filter, criteria);
928 TypeContainer tc = (TypeContainer) builder_to_container [t];
931 return tc.FindMembers (mt, bf, filter, criteria);
936 public static bool IsBuiltinType (Type t)
938 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
939 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
940 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
941 t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
947 public static bool IsDelegateType (Type t)
949 if (t.IsSubclassOf (TypeManager.delegate_type))
955 public static bool IsEnumType (Type t)
957 if (t.IsSubclassOf (TypeManager.enum_type))
963 public static bool IsValueType (Type t)
965 if (t.IsSubclassOf (TypeManager.value_type))
971 public static bool IsInterfaceType (Type t)
973 Interface iface = (Interface) builder_to_interface [t];
982 // Checks whether `type' is a subclass or nested child of `parent'.
984 public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
987 if (type.IsSubclassOf (parent))
990 // Handle nested types.
991 type = type.DeclaringType;
992 } while (type != null);
998 /// Returns the User Defined Types
1000 public static ArrayList UserTypes {
1006 public static Hashtable TypeContainers {
1008 return typecontainers;
1012 static Hashtable builder_to_constant;
1014 public static void RegisterConstant (FieldBuilder fb, Const c)
1016 if (builder_to_constant == null)
1017 builder_to_constant = new PtrHashtable ();
1019 if (builder_to_constant.Contains (fb))
1022 builder_to_constant.Add (fb, c);
1025 public static Const LookupConstant (FieldBuilder fb)
1027 if (builder_to_constant == null)
1030 return (Const) builder_to_constant [fb];
1034 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1038 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1039 /// for anything which is dynamic, and we need this in a number of places,
1040 /// we register this information here, and use it afterwards.
1042 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1047 method_arguments.Add (mb, args);
1048 method_internal_params.Add (mb, ip);
1053 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1055 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1058 if (method_internal_params.Contains (mb))
1059 return (InternalParameters) method_internal_params [mb];
1061 throw new Exception ("Argument for Method not registered" + mb);
1065 /// Returns the argument types for a method based on its methodbase
1067 /// For dynamic methods, we use the compiler provided types, for
1068 /// methods from existing assemblies we load them from GetParameters,
1069 /// and insert them into the cache
1071 static public Type [] GetArgumentTypes (MethodBase mb)
1073 if (method_arguments.Contains (mb))
1074 return (Type []) method_arguments [mb];
1076 ParameterInfo [] pi = mb.GetParameters ();
1078 Type [] types = new Type [c];
1080 for (int i = 0; i < c; i++)
1081 types [i] = pi [i].ParameterType;
1083 method_arguments.Add (mb, types);
1089 /// Returns the argument types for an indexer based on its PropertyInfo
1091 /// For dynamic indexers, we use the compiler provided types, for
1092 /// indexers from existing assemblies we load them from GetParameters,
1093 /// and insert them into the cache
1095 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1097 if (indexer_arguments.Contains (indexer))
1098 return (Type []) indexer_arguments [indexer];
1099 else if (indexer is PropertyBuilder)
1100 // If we're a PropertyBuilder and not in the
1101 // `indexer_arguments' hash, then we're a property and
1105 ParameterInfo [] pi = indexer.GetIndexParameters ();
1106 // Property, not an indexer.
1110 Type [] types = new Type [c];
1112 for (int i = 0; i < c; i++)
1113 types [i] = pi [i].ParameterType;
1115 indexer_arguments.Add (indexer, types);
1121 // This is a workaround the fact that GetValue is not
1122 // supported for dynamic types
1124 static Hashtable fields = new Hashtable ();
1125 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1127 if (fields.Contains (fb))
1130 fields.Add (fb, value);
1135 static public object GetValue (FieldBuilder fb)
1140 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1141 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1143 if (fieldbuilders_to_fields.Contains (fb))
1146 fieldbuilders_to_fields.Add (fb, f);
1150 static public FieldBase GetField (FieldInfo fb)
1152 return (FieldBase) fieldbuilders_to_fields [fb];
1155 static Hashtable events;
1157 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1160 events = new Hashtable ();
1162 if (events.Contains (eb))
1165 events.Add (eb, new Pair (add, remove));
1170 static public MethodInfo GetAddMethod (EventInfo ei)
1172 if (ei is MyEventBuilder) {
1173 Pair pair = (Pair) events [ei];
1175 return (MethodInfo) pair.First;
1177 return ei.GetAddMethod ();
1180 static public MethodInfo GetRemoveMethod (EventInfo ei)
1182 if (ei is MyEventBuilder) {
1183 Pair pair = (Pair) events [ei];
1185 return (MethodInfo) pair.Second;
1187 return ei.GetAddMethod ();
1190 static Hashtable priv_fields_events;
1192 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1194 if (priv_fields_events == null)
1195 priv_fields_events = new Hashtable ();
1197 if (priv_fields_events.Contains (einfo))
1200 priv_fields_events.Add (einfo, builder);
1205 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1207 return (MemberInfo) priv_fields_events [ei];
1210 static Hashtable properties;
1212 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1214 if (properties == null)
1215 properties = new Hashtable ();
1217 if (properties.Contains (pb))
1220 properties.Add (pb, new Pair (get, set));
1225 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
1227 if (!RegisterProperty (pb, get,set))
1230 indexer_arguments.Add (pb, args);
1236 // FIXME: we need to return the accessors depending on whether
1237 // they are visible or not.
1239 static public MethodInfo [] GetAccessors (PropertyInfo pi)
1243 if (pi is PropertyBuilder){
1244 Pair pair = (Pair) properties [pi];
1246 ret = new MethodInfo [2];
1247 ret [0] = (MethodInfo) pair.First;
1248 ret [1] = (MethodInfo) pair.Second;
1252 MethodInfo [] mi = new MethodInfo [2];
1255 // Why this and not pi.GetAccessors?
1256 // Because sometimes index 0 is the getter
1257 // sometimes it is 1
1259 mi [0] = pi.GetGetMethod (true);
1260 mi [1] = pi.GetSetMethod (true);
1266 static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1268 if (pi is PropertyBuilder){
1269 Pair de = (Pair) properties [pi];
1271 return (MethodInfo) de.Second;
1273 return pi.GetSetMethod ();
1276 static public MethodInfo GetPropertySetter (PropertyInfo pi)
1278 if (pi is PropertyBuilder){
1279 Pair de = (Pair) properties [pi];
1281 return (MethodInfo) de.First;
1283 return pi.GetGetMethod ();
1287 /// Given an array of interface types, expand and eliminate repeated ocurrences
1288 /// of an interface.
1292 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1295 public static Type [] ExpandInterfaces (Type [] base_interfaces)
1297 ArrayList new_ifaces = new ArrayList ();
1299 foreach (Type iface in base_interfaces){
1300 if (!new_ifaces.Contains (iface))
1301 new_ifaces.Add (iface);
1303 Type [] implementing = TypeManager.GetInterfaces (iface);
1305 foreach (Type imp in implementing){
1306 if (!new_ifaces.Contains (imp))
1307 new_ifaces.Add (imp);
1310 Type [] ret = new Type [new_ifaces.Count];
1311 new_ifaces.CopyTo (ret, 0);
1316 /// This function returns the interfaces in the type `t'. Works with
1317 /// both types and TypeBuilders.
1319 public static Type [] GetInterfaces (Type t)
1322 // The reason for catching the Array case is that Reflection.Emit
1323 // will not return a TypeBuilder for Array types of TypeBuilder types,
1324 // but will still throw an exception if we try to call GetInterfaces
1327 // Since the array interfaces are always constant, we return those for
1332 t = TypeManager.array_type;
1334 if (t is TypeBuilder){
1335 Type [] parent_ifaces;
1337 if (t.BaseType == null)
1338 parent_ifaces = NoTypes;
1340 parent_ifaces = GetInterfaces (t.BaseType);
1341 Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1342 if (type_ifaces == null)
1343 type_ifaces = NoTypes;
1345 int parent_count = parent_ifaces.Length;
1346 Type [] result = new Type [parent_count + type_ifaces.Length];
1347 parent_ifaces.CopyTo (result, 0);
1348 type_ifaces.CopyTo (result, parent_count);
1352 return t.GetInterfaces ();
1356 /// The following is used to check if a given type implements an interface.
1357 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1359 public static bool ImplementsInterface (Type t, Type iface)
1364 // FIXME OPTIMIZATION:
1365 // as soon as we hit a non-TypeBuiler in the interface
1366 // chain, we could return, as the `Type.GetInterfaces'
1367 // will return all the interfaces implement by the type
1371 interfaces = GetInterfaces (t);
1373 if (interfaces != null){
1374 foreach (Type i in interfaces){
1381 } while (t != null);
1386 // This is a custom version of Convert.ChangeType() which works
1387 // with the TypeBuilder defined types when compiling corlib.
1388 public static object ChangeType (object value, Type conversionType)
1390 if (!(value is IConvertible))
1391 throw new ArgumentException ();
1393 IConvertible convertValue = (IConvertible) value;
1394 CultureInfo ci = CultureInfo.CurrentCulture;
1395 NumberFormatInfo provider = ci.NumberFormat;
1398 // We must use Type.Equals() here since `conversionType' is
1399 // the TypeBuilder created version of a system type and not
1400 // the system type itself. You cannot use Type.GetTypeCode()
1401 // on such a type - it'd always return TypeCode.Object.
1403 if (conversionType.Equals (typeof (Boolean)))
1404 return (object)(convertValue.ToBoolean (provider));
1405 else if (conversionType.Equals (typeof (Byte)))
1406 return (object)(convertValue.ToByte (provider));
1407 else if (conversionType.Equals (typeof (Char)))
1408 return (object)(convertValue.ToChar (provider));
1409 else if (conversionType.Equals (typeof (DateTime)))
1410 return (object)(convertValue.ToDateTime (provider));
1411 else if (conversionType.Equals (typeof (Decimal)))
1412 return (object)(convertValue.ToDecimal (provider));
1413 else if (conversionType.Equals (typeof (Double)))
1414 return (object)(convertValue.ToDouble (provider));
1415 else if (conversionType.Equals (typeof (Int16)))
1416 return (object)(convertValue.ToInt16 (provider));
1417 else if (conversionType.Equals (typeof (Int32)))
1418 return (object)(convertValue.ToInt32 (provider));
1419 else if (conversionType.Equals (typeof (Int64)))
1420 return (object)(convertValue.ToInt64 (provider));
1421 else if (conversionType.Equals (typeof (SByte)))
1422 return (object)(convertValue.ToSByte (provider));
1423 else if (conversionType.Equals (typeof (Single)))
1424 return (object)(convertValue.ToSingle (provider));
1425 else if (conversionType.Equals (typeof (String)))
1426 return (object)(convertValue.ToString (provider));
1427 else if (conversionType.Equals (typeof (UInt16)))
1428 return (object)(convertValue.ToUInt16 (provider));
1429 else if (conversionType.Equals (typeof (UInt32)))
1430 return (object)(convertValue.ToUInt32 (provider));
1431 else if (conversionType.Equals (typeof (UInt64)))
1432 return (object)(convertValue.ToUInt64 (provider));
1433 else if (conversionType.Equals (typeof (Object)))
1434 return (object)(value);
1436 throw new InvalidCastException ();
1440 // This is needed, because enumerations from assemblies
1441 // do not report their underlyingtype, but they report
1444 public static Type EnumToUnderlying (Type t)
1446 if (t == TypeManager.enum_type)
1449 t = t.UnderlyingSystemType;
1450 if (!TypeManager.IsEnumType (t))
1453 if (t is TypeBuilder) {
1454 // slow path needed to compile corlib
1455 if (t == TypeManager.bool_type ||
1456 t == TypeManager.byte_type ||
1457 t == TypeManager.sbyte_type ||
1458 t == TypeManager.char_type ||
1459 t == TypeManager.short_type ||
1460 t == TypeManager.ushort_type ||
1461 t == TypeManager.int32_type ||
1462 t == TypeManager.uint32_type ||
1463 t == TypeManager.int64_type ||
1464 t == TypeManager.uint64_type)
1466 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1468 TypeCode tc = Type.GetTypeCode (t);
1471 case TypeCode.Boolean:
1472 return TypeManager.bool_type;
1474 return TypeManager.byte_type;
1475 case TypeCode.SByte:
1476 return TypeManager.sbyte_type;
1478 return TypeManager.char_type;
1479 case TypeCode.Int16:
1480 return TypeManager.short_type;
1481 case TypeCode.UInt16:
1482 return TypeManager.ushort_type;
1483 case TypeCode.Int32:
1484 return TypeManager.int32_type;
1485 case TypeCode.UInt32:
1486 return TypeManager.uint32_type;
1487 case TypeCode.Int64:
1488 return TypeManager.int64_type;
1489 case TypeCode.UInt64:
1490 return TypeManager.uint64_type;
1492 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1496 // When compiling corlib and called with one of the core types, return
1497 // the corresponding typebuilder for that type.
1499 public static Type TypeToCoreType (Type t)
1501 if (RootContext.StdLib || (t is TypeBuilder))
1504 TypeCode tc = Type.GetTypeCode (t);
1507 case TypeCode.Boolean:
1508 return TypeManager.bool_type;
1510 return TypeManager.byte_type;
1511 case TypeCode.SByte:
1512 return TypeManager.sbyte_type;
1514 return TypeManager.char_type;
1515 case TypeCode.Int16:
1516 return TypeManager.short_type;
1517 case TypeCode.UInt16:
1518 return TypeManager.ushort_type;
1519 case TypeCode.Int32:
1520 return TypeManager.int32_type;
1521 case TypeCode.UInt32:
1522 return TypeManager.uint32_type;
1523 case TypeCode.Int64:
1524 return TypeManager.int64_type;
1525 case TypeCode.UInt64:
1526 return TypeManager.uint64_type;
1527 case TypeCode.String:
1528 return TypeManager.string_type;
1530 if (t == typeof (void))
1531 return TypeManager.void_type;
1532 if (t == typeof (object))
1533 return TypeManager.object_type;
1534 if (t == typeof (System.Type))
1535 return TypeManager.type_type;
1541 /// Utility function that can be used to probe whether a type
1542 /// is managed or not.
1544 public static bool VerifyUnManaged (Type t, Location loc)
1546 if (t.IsValueType || t.IsPointer){
1548 // FIXME: this is more complex, we actually need to
1549 // make sure that the type does not contain any
1555 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1556 // We need this explicit check here to make it work when
1557 // compiling corlib.
1562 "Cannot take the address or size of a variable of a managed type ('" +
1563 CSharpName (t) + "')");
1568 /// Returns the name of the indexer in a given type.
1571 /// The default is not always `Item'. The user can change this behaviour by
1572 /// using the DefaultMemberAttribute in the class.
1574 /// For example, the String class indexer is named `Chars' not `Item'
1576 public static string IndexerPropertyName (Type t)
1578 if (t is TypeBuilder) {
1579 if (t.IsInterface) {
1580 Interface i = LookupInterface (t);
1582 if ((i == null) || (i.IndexerName == null))
1585 return i.IndexerName;
1587 TypeContainer tc = LookupTypeContainer (t);
1589 if ((tc == null) || (tc.IndexerName == null))
1592 return tc.IndexerName;
1596 System.Attribute attr = System.Attribute.GetCustomAttribute (
1597 t, TypeManager.default_member_type);
1599 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1600 return dma.MemberName;
1606 public static void MakePinned (LocalBuilder builder)
1609 // FIXME: Flag the "LocalBuilder" type as being
1610 // pinned. Figure out API.
1616 // Returns whether the array of memberinfos contains the given method
1618 static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1620 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1622 foreach (MethodBase method in array){
1623 if (method.Name != new_method.Name)
1626 Type [] old_args = TypeManager.GetArgumentTypes (method);
1627 int old_count = old_args.Length;
1630 if (new_args.Length != old_count)
1633 for (i = 0; i < old_count; i++){
1634 if (old_args [i] != new_args [i])
1646 // We copy methods from `new_members' into `target_list' if the signature
1647 // for the method from in the new list does not exist in the target_list
1649 // The name is assumed to be the same.
1651 public static ArrayList CopyNewMethods (ArrayList target_list, MemberInfo [] new_members)
1653 if (target_list == null){
1654 target_list = new ArrayList ();
1656 foreach (MemberInfo mi in new_members){
1657 if (mi is MethodBase)
1658 target_list.Add (mi);
1663 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1664 target_list.CopyTo (target_array, 0);
1666 foreach (MemberInfo mi in new_members){
1667 MethodBase new_method = (MethodBase) mi;
1669 if (!ArrayContainsMethod (target_array, new_method))
1670 target_list.Add (new_method);
1676 public enum MethodFlags {
1678 IsObsoleteError = 2,
1683 // Returns the TypeManager.MethodFlags for this method.
1684 // This emits an error 619 / warning 618 if the method is obsolete.
1685 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
1687 static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
1689 MethodFlags flags = 0;
1691 if (mb.DeclaringType is TypeBuilder){
1692 MethodData method = (MethodData) builder_to_method [mb];
1693 if (method == null) {
1694 // FIXME: implement Obsolete attribute on Property,
1695 // Indexer and Event.
1699 return method.GetMethodFlags (loc);
1702 object [] attrs = mb.GetCustomAttributes (true);
1703 foreach (object ta in attrs){
1704 if (!(ta is System.Attribute)){
1705 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
1708 System.Attribute a = (System.Attribute) ta;
1709 if (a.TypeId == TypeManager.obsolete_attribute_type){
1710 ObsoleteAttribute oa = (ObsoleteAttribute) a;
1712 string method_desc = TypeManager.CSharpSignature (mb);
1715 Report.Error (619, loc, "Method `" + method_desc +
1716 "' is obsolete: `" + oa.Message + "'");
1717 return MethodFlags.IsObsoleteError;
1719 Report.Warning (618, loc, "Method `" + method_desc +
1720 "' is obsolete: `" + oa.Message + "'");
1722 flags |= MethodFlags.IsObsolete;
1728 // Skip over conditional code.
1730 if (a.TypeId == TypeManager.conditional_attribute_type){
1731 ConditionalAttribute ca = (ConditionalAttribute) a;
1733 if (RootContext.AllDefines [ca.ConditionString] == null)
1734 flags |= MethodFlags.ShouldIgnore;
1741 #region MemberLookup implementation
1744 // Name of the member
1746 static string closure_name;
1749 // Whether we allow private members in the result (since FindMembers
1750 // uses NonPublic for both protected and private), we need to distinguish.
1752 static bool closure_private_ok;
1755 // Who is invoking us and which type is being queried currently.
1757 static Type closure_invocation_type;
1758 static Type closure_queried_type;
1759 static Type closure_start_type;
1762 // The assembly that defines the type is that is calling us
1764 static Assembly closure_invocation_assembly;
1767 // This filter filters by name + whether it is ok to include private
1768 // members in the search
1770 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1773 // Hack: we know that the filter criteria will always be in the `closure'
1777 if (m.Name != closure_name)
1781 // Ugly: we need to find out the type of `m', and depending
1782 // on this, tell whether we accept or not
1784 if (m is MethodBase){
1785 MethodBase mb = (MethodBase) m;
1786 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1788 if (ma == MethodAttributes.Private)
1789 return closure_private_ok;
1792 // FamAndAssem requires that we not only derivate, but we are on the
1795 if (ma == MethodAttributes.FamANDAssem){
1796 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1800 // Assembly and FamORAssem succeed if we're in the same assembly.
1801 if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
1802 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
1806 // We already know that we aren't in the same assembly.
1807 if (ma == MethodAttributes.Assembly)
1810 // Family and FamANDAssem require that we derive.
1811 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
1812 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
1815 // Although a derived class can access protected members of its base class
1816 // it cannot do so through an instance of the base class (CS1540).
1817 if ((closure_invocation_type != closure_start_type) &&
1818 closure_invocation_type.IsSubclassOf (closure_start_type))
1828 if (m is FieldInfo){
1829 FieldInfo fi = (FieldInfo) m;
1830 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
1832 if (fa == FieldAttributes.Private)
1833 return closure_private_ok;
1836 // FamAndAssem requires that we not only derivate, but we are on the
1839 if (fa == FieldAttributes.FamANDAssem){
1840 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
1844 // Assembly and FamORAssem succeed if we're in the same assembly.
1845 if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
1846 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
1850 // We already know that we aren't in the same assembly.
1851 if (fa == FieldAttributes.Assembly)
1854 // Family and FamANDAssem require that we derive.
1855 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
1856 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
1859 // Although a derived class can access protected members of its base class
1860 // it cannot do so through an instance of the base class (CS1540).
1861 if ((closure_invocation_type != closure_start_type) &&
1862 closure_invocation_type.IsSubclassOf (closure_start_type))
1873 // EventInfos and PropertyInfos, return true
1878 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
1881 // Looks up a member called `name' in the `queried_type'. This lookup
1882 // is done by code that is contained in the definition for `invocation_type'.
1884 // The binding flags are `bf' and the kind of members being looked up are `mt'
1886 // Returns an array of a single element for everything but Methods/Constructors
1887 // that might return multiple matches.
1889 public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type,
1890 MemberTypes mt, BindingFlags original_bf, string name)
1892 BindingFlags bf = original_bf;
1894 ArrayList method_list = null;
1895 Type current_type = queried_type;
1896 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
1898 bool always_ok_flag = false;
1900 closure_name = name;
1901 closure_invocation_type = invocation_type;
1902 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
1903 closure_start_type = queried_type;
1906 // If we are a nested class, we always have access to our container
1909 if (invocation_type != null){
1910 string invocation_name = invocation_type.FullName;
1911 if (invocation_name.IndexOf ('+') != -1){
1912 string container = queried_type.FullName + "+";
1913 int container_length = container.Length;
1915 if (invocation_name.Length > container_length){
1916 string shared = invocation_name.Substring (0, container_length);
1918 if (shared == container)
1919 always_ok_flag = true;
1928 // `NonPublic' is lame, because it includes both protected and
1929 // private methods, so we need to control this behavior by
1930 // explicitly tracking if a private method is ok or not.
1932 // The possible cases are:
1933 // public, private and protected (internal does not come into the
1936 if (invocation_type != null){
1937 if (invocation_type == current_type){
1940 private_ok = always_ok_flag;
1942 if (private_ok || invocation_type.IsSubclassOf (current_type))
1943 bf = original_bf | BindingFlags.NonPublic;
1946 bf = original_bf & ~BindingFlags.NonPublic;
1949 closure_private_ok = private_ok;
1950 closure_queried_type = current_type;
1952 mi = TypeManager.FindMembers (
1953 current_type, mt, bf | BindingFlags.DeclaredOnly,
1954 FilterWithClosure_delegate, name);
1956 if (current_type == TypeManager.object_type)
1959 current_type = current_type.BaseType;
1962 // This happens with interfaces, they have a null
1963 // basetype. Look members up in the Object class.
1965 if (current_type == null)
1966 current_type = TypeManager.object_type;
1972 int count = mi.Length;
1978 // Events and types are returned by both `static' and `instance'
1979 // searches, which means that our above FindMembers will
1980 // return two copies of the same.
1982 if (count == 1 && !(mi [0] is MethodBase)){
1987 // Multiple properties: we query those just to find out the indexer
1990 if (mi [0] is PropertyInfo)
1994 // We found methods, turn the search into "method scan"
1998 method_list = CopyNewMethods (method_list, mi);
1999 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2000 } while (searching);
2002 if (method_list != null && method_list.Count > 0)
2003 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2006 // Interfaces do not list members they inherit, so we have to
2009 if (!queried_type.IsInterface)
2012 if (queried_type.IsArray)
2013 queried_type = TypeManager.array_type;
2015 Type [] ifaces = GetInterfaces (queried_type);
2019 foreach (Type itype in ifaces){
2022 x = MemberLookup (null, itype, mt, bf, name);