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 /// Returns the User Defined Types
984 public static ArrayList UserTypes {
990 public static Hashtable TypeContainers {
992 return typecontainers;
996 static Hashtable builder_to_constant;
998 public static void RegisterConstant (FieldBuilder fb, Const c)
1000 if (builder_to_constant == null)
1001 builder_to_constant = new PtrHashtable ();
1003 if (builder_to_constant.Contains (fb))
1006 builder_to_constant.Add (fb, c);
1009 public static Const LookupConstant (FieldBuilder fb)
1011 if (builder_to_constant == null)
1014 return (Const) builder_to_constant [fb];
1018 /// Gigantic work around for missing features in System.Reflection.Emit follows.
1022 /// Since System.Reflection.Emit can not return MethodBase.GetParameters
1023 /// for anything which is dynamic, and we need this in a number of places,
1024 /// we register this information here, and use it afterwards.
1026 static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1031 method_arguments.Add (mb, args);
1032 method_internal_params.Add (mb, ip);
1037 static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1039 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1042 if (method_internal_params.Contains (mb))
1043 return (InternalParameters) method_internal_params [mb];
1045 throw new Exception ("Argument for Method not registered" + mb);
1049 /// Returns the argument types for a method based on its methodbase
1051 /// For dynamic methods, we use the compiler provided types, for
1052 /// methods from existing assemblies we load them from GetParameters,
1053 /// and insert them into the cache
1055 static public Type [] GetArgumentTypes (MethodBase mb)
1057 if (method_arguments.Contains (mb))
1058 return (Type []) method_arguments [mb];
1060 ParameterInfo [] pi = mb.GetParameters ();
1062 Type [] types = new Type [c];
1064 for (int i = 0; i < c; i++)
1065 types [i] = pi [i].ParameterType;
1067 method_arguments.Add (mb, types);
1073 /// Returns the argument types for an indexer based on its PropertyInfo
1075 /// For dynamic indexers, we use the compiler provided types, for
1076 /// indexers from existing assemblies we load them from GetParameters,
1077 /// and insert them into the cache
1079 static public Type [] GetArgumentTypes (PropertyInfo indexer)
1081 if (indexer_arguments.Contains (indexer))
1082 return (Type []) indexer_arguments [indexer];
1083 else if (indexer is PropertyBuilder)
1084 // If we're a PropertyBuilder and not in the
1085 // `indexer_arguments' hash, then we're a property and
1089 ParameterInfo [] pi = indexer.GetIndexParameters ();
1090 // Property, not an indexer.
1094 Type [] types = new Type [c];
1096 for (int i = 0; i < c; i++)
1097 types [i] = pi [i].ParameterType;
1099 indexer_arguments.Add (indexer, types);
1105 // This is a workaround the fact that GetValue is not
1106 // supported for dynamic types
1108 static Hashtable fields = new Hashtable ();
1109 static public bool RegisterFieldValue (FieldBuilder fb, object value)
1111 if (fields.Contains (fb))
1114 fields.Add (fb, value);
1119 static public object GetValue (FieldBuilder fb)
1124 static Hashtable fieldbuilders_to_fields = new Hashtable ();
1125 static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1127 if (fieldbuilders_to_fields.Contains (fb))
1130 fieldbuilders_to_fields.Add (fb, f);
1134 static public FieldBase GetField (FieldInfo fb)
1136 return (FieldBase) fieldbuilders_to_fields [fb];
1139 static Hashtable events;
1141 static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1144 events = new Hashtable ();
1146 if (events.Contains (eb))
1149 events.Add (eb, new Pair (add, remove));
1154 static public MethodInfo GetAddMethod (EventInfo ei)
1156 if (ei is MyEventBuilder) {
1157 Pair pair = (Pair) events [ei];
1159 return (MethodInfo) pair.First;
1161 return ei.GetAddMethod ();
1164 static public MethodInfo GetRemoveMethod (EventInfo ei)
1166 if (ei is MyEventBuilder) {
1167 Pair pair = (Pair) events [ei];
1169 return (MethodInfo) pair.Second;
1171 return ei.GetAddMethod ();
1174 static Hashtable priv_fields_events;
1176 static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1178 if (priv_fields_events == null)
1179 priv_fields_events = new Hashtable ();
1181 if (priv_fields_events.Contains (einfo))
1184 priv_fields_events.Add (einfo, builder);
1189 static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1191 return (MemberInfo) priv_fields_events [ei];
1194 static Hashtable properties;
1196 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1198 if (properties == null)
1199 properties = new Hashtable ();
1201 if (properties.Contains (pb))
1204 properties.Add (pb, new Pair (get, set));
1209 static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
1211 if (!RegisterProperty (pb, get,set))
1214 indexer_arguments.Add (pb, args);
1220 // FIXME: we need to return the accessors depending on whether
1221 // they are visible or not.
1223 static public MethodInfo [] GetAccessors (PropertyInfo pi)
1227 if (pi is PropertyBuilder){
1228 Pair pair = (Pair) properties [pi];
1230 ret = new MethodInfo [2];
1231 ret [0] = (MethodInfo) pair.First;
1232 ret [1] = (MethodInfo) pair.Second;
1236 MethodInfo [] mi = new MethodInfo [2];
1239 // Why this and not pi.GetAccessors?
1240 // Because sometimes index 0 is the getter
1241 // sometimes it is 1
1243 mi [0] = pi.GetGetMethod (true);
1244 mi [1] = pi.GetSetMethod (true);
1250 static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1252 if (pi is PropertyBuilder){
1253 Pair de = (Pair) properties [pi];
1255 return (MethodInfo) de.Second;
1257 return pi.GetSetMethod ();
1260 static public MethodInfo GetPropertySetter (PropertyInfo pi)
1262 if (pi is PropertyBuilder){
1263 Pair de = (Pair) properties [pi];
1265 return (MethodInfo) de.First;
1267 return pi.GetGetMethod ();
1271 /// Given an array of interface types, expand and eliminate repeated ocurrences
1272 /// of an interface.
1276 /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1279 public static Type [] ExpandInterfaces (Type [] base_interfaces)
1281 ArrayList new_ifaces = new ArrayList ();
1283 foreach (Type iface in base_interfaces){
1284 if (!new_ifaces.Contains (iface))
1285 new_ifaces.Add (iface);
1287 Type [] implementing = TypeManager.GetInterfaces (iface);
1289 foreach (Type imp in implementing){
1290 if (!new_ifaces.Contains (imp))
1291 new_ifaces.Add (imp);
1294 Type [] ret = new Type [new_ifaces.Count];
1295 new_ifaces.CopyTo (ret, 0);
1300 /// This function returns the interfaces in the type `t'. Works with
1301 /// both types and TypeBuilders.
1303 public static Type [] GetInterfaces (Type t)
1306 // The reason for catching the Array case is that Reflection.Emit
1307 // will not return a TypeBuilder for Array types of TypeBuilder types,
1308 // but will still throw an exception if we try to call GetInterfaces
1311 // Since the array interfaces are always constant, we return those for
1316 t = TypeManager.array_type;
1318 if (t is TypeBuilder){
1319 Type [] parent_ifaces;
1321 if (t.BaseType == null)
1322 parent_ifaces = NoTypes;
1324 parent_ifaces = GetInterfaces (t.BaseType);
1325 Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1326 if (type_ifaces == null)
1327 type_ifaces = NoTypes;
1329 int parent_count = parent_ifaces.Length;
1330 Type [] result = new Type [parent_count + type_ifaces.Length];
1331 parent_ifaces.CopyTo (result, 0);
1332 type_ifaces.CopyTo (result, parent_count);
1336 return t.GetInterfaces ();
1340 /// The following is used to check if a given type implements an interface.
1341 /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1343 public static bool ImplementsInterface (Type t, Type iface)
1348 // FIXME OPTIMIZATION:
1349 // as soon as we hit a non-TypeBuiler in the interface
1350 // chain, we could return, as the `Type.GetInterfaces'
1351 // will return all the interfaces implement by the type
1355 interfaces = GetInterfaces (t);
1357 if (interfaces != null){
1358 foreach (Type i in interfaces){
1365 } while (t != null);
1370 // This is a custom version of Convert.ChangeType() which works
1371 // with the TypeBuilder defined types when compiling corlib.
1372 public static object ChangeType (object value, Type conversionType)
1374 if (!(value is IConvertible))
1375 throw new ArgumentException ();
1377 IConvertible convertValue = (IConvertible) value;
1378 CultureInfo ci = CultureInfo.CurrentCulture;
1379 NumberFormatInfo provider = ci.NumberFormat;
1382 // We must use Type.Equals() here since `conversionType' is
1383 // the TypeBuilder created version of a system type and not
1384 // the system type itself. You cannot use Type.GetTypeCode()
1385 // on such a type - it'd always return TypeCode.Object.
1387 if (conversionType.Equals (typeof (Boolean)))
1388 return (object)(convertValue.ToBoolean (provider));
1389 else if (conversionType.Equals (typeof (Byte)))
1390 return (object)(convertValue.ToByte (provider));
1391 else if (conversionType.Equals (typeof (Char)))
1392 return (object)(convertValue.ToChar (provider));
1393 else if (conversionType.Equals (typeof (DateTime)))
1394 return (object)(convertValue.ToDateTime (provider));
1395 else if (conversionType.Equals (typeof (Decimal)))
1396 return (object)(convertValue.ToDecimal (provider));
1397 else if (conversionType.Equals (typeof (Double)))
1398 return (object)(convertValue.ToDouble (provider));
1399 else if (conversionType.Equals (typeof (Int16)))
1400 return (object)(convertValue.ToInt16 (provider));
1401 else if (conversionType.Equals (typeof (Int32)))
1402 return (object)(convertValue.ToInt32 (provider));
1403 else if (conversionType.Equals (typeof (Int64)))
1404 return (object)(convertValue.ToInt64 (provider));
1405 else if (conversionType.Equals (typeof (SByte)))
1406 return (object)(convertValue.ToSByte (provider));
1407 else if (conversionType.Equals (typeof (Single)))
1408 return (object)(convertValue.ToSingle (provider));
1409 else if (conversionType.Equals (typeof (String)))
1410 return (object)(convertValue.ToString (provider));
1411 else if (conversionType.Equals (typeof (UInt16)))
1412 return (object)(convertValue.ToUInt16 (provider));
1413 else if (conversionType.Equals (typeof (UInt32)))
1414 return (object)(convertValue.ToUInt32 (provider));
1415 else if (conversionType.Equals (typeof (UInt64)))
1416 return (object)(convertValue.ToUInt64 (provider));
1417 else if (conversionType.Equals (typeof (Object)))
1418 return (object)(value);
1420 throw new InvalidCastException ();
1424 // This is needed, because enumerations from assemblies
1425 // do not report their underlyingtype, but they report
1428 public static Type EnumToUnderlying (Type t)
1430 if (t == TypeManager.enum_type)
1433 t = t.UnderlyingSystemType;
1434 if (!TypeManager.IsEnumType (t))
1437 if (t is TypeBuilder) {
1438 // slow path needed to compile corlib
1439 if (t == TypeManager.bool_type ||
1440 t == TypeManager.byte_type ||
1441 t == TypeManager.sbyte_type ||
1442 t == TypeManager.char_type ||
1443 t == TypeManager.short_type ||
1444 t == TypeManager.ushort_type ||
1445 t == TypeManager.int32_type ||
1446 t == TypeManager.uint32_type ||
1447 t == TypeManager.int64_type ||
1448 t == TypeManager.uint64_type)
1450 throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1452 TypeCode tc = Type.GetTypeCode (t);
1455 case TypeCode.Boolean:
1456 return TypeManager.bool_type;
1458 return TypeManager.byte_type;
1459 case TypeCode.SByte:
1460 return TypeManager.sbyte_type;
1462 return TypeManager.char_type;
1463 case TypeCode.Int16:
1464 return TypeManager.short_type;
1465 case TypeCode.UInt16:
1466 return TypeManager.ushort_type;
1467 case TypeCode.Int32:
1468 return TypeManager.int32_type;
1469 case TypeCode.UInt32:
1470 return TypeManager.uint32_type;
1471 case TypeCode.Int64:
1472 return TypeManager.int64_type;
1473 case TypeCode.UInt64:
1474 return TypeManager.uint64_type;
1476 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1480 // When compiling corlib and called with one of the core types, return
1481 // the corresponding typebuilder for that type.
1483 public static Type TypeToCoreType (Type t)
1485 if (RootContext.StdLib || (t is TypeBuilder))
1488 TypeCode tc = Type.GetTypeCode (t);
1491 case TypeCode.Boolean:
1492 return TypeManager.bool_type;
1494 return TypeManager.byte_type;
1495 case TypeCode.SByte:
1496 return TypeManager.sbyte_type;
1498 return TypeManager.char_type;
1499 case TypeCode.Int16:
1500 return TypeManager.short_type;
1501 case TypeCode.UInt16:
1502 return TypeManager.ushort_type;
1503 case TypeCode.Int32:
1504 return TypeManager.int32_type;
1505 case TypeCode.UInt32:
1506 return TypeManager.uint32_type;
1507 case TypeCode.Int64:
1508 return TypeManager.int64_type;
1509 case TypeCode.UInt64:
1510 return TypeManager.uint64_type;
1511 case TypeCode.String:
1512 return TypeManager.string_type;
1514 if (t == typeof (void))
1515 return TypeManager.void_type;
1516 if (t == typeof (object))
1517 return TypeManager.object_type;
1518 if (t == typeof (System.Type))
1519 return TypeManager.type_type;
1525 /// Utility function that can be used to probe whether a type
1526 /// is managed or not.
1528 public static bool VerifyUnManaged (Type t, Location loc)
1530 if (t.IsValueType || t.IsPointer){
1532 // FIXME: this is more complex, we actually need to
1533 // make sure that the type does not contain any
1539 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1540 // We need this explicit check here to make it work when
1541 // compiling corlib.
1546 "Cannot take the address or size of a variable of a managed type ('" +
1547 CSharpName (t) + "')");
1552 /// Returns the name of the indexer in a given type.
1555 /// The default is not always `Item'. The user can change this behaviour by
1556 /// using the DefaultMemberAttribute in the class.
1558 /// For example, the String class indexer is named `Chars' not `Item'
1560 public static string IndexerPropertyName (Type t)
1562 if (t is TypeBuilder) {
1563 if (t.IsInterface) {
1564 Interface i = LookupInterface (t);
1566 if ((i == null) || (i.IndexerName == null))
1569 return i.IndexerName;
1571 TypeContainer tc = LookupTypeContainer (t);
1573 if ((tc == null) || (tc.IndexerName == null))
1576 return tc.IndexerName;
1580 System.Attribute attr = System.Attribute.GetCustomAttribute (
1581 t, TypeManager.default_member_type);
1583 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1584 return dma.MemberName;
1590 public static void MakePinned (LocalBuilder builder)
1593 // FIXME: Flag the "LocalBuilder" type as being
1594 // pinned. Figure out API.
1600 // Returns whether the array of memberinfos contains the given method
1602 static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1604 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1606 foreach (MethodBase method in array){
1607 if (method.Name != new_method.Name)
1610 Type [] old_args = TypeManager.GetArgumentTypes (method);
1611 int old_count = old_args.Length;
1614 if (new_args.Length != old_count)
1617 for (i = 0; i < old_count; i++){
1618 if (old_args [i] != new_args [i])
1630 // We copy methods from `new_members' into `target_list' if the signature
1631 // for the method from in the new list does not exist in the target_list
1633 // The name is assumed to be the same.
1635 public static ArrayList CopyNewMethods (ArrayList target_list, MemberInfo [] new_members)
1637 if (target_list == null){
1638 target_list = new ArrayList ();
1640 foreach (MemberInfo mi in new_members){
1641 if (mi is MethodBase)
1642 target_list.Add (mi);
1647 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1648 target_list.CopyTo (target_array, 0);
1650 foreach (MemberInfo mi in new_members){
1651 MethodBase new_method = (MethodBase) mi;
1653 if (!ArrayContainsMethod (target_array, new_method))
1654 target_list.Add (new_method);
1660 public enum MethodFlags {
1662 IsObsoleteError = 2,
1667 // Returns the TypeManager.MethodFlags for this method.
1668 // This emits an error 619 / warning 618 if the method is obsolete.
1669 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
1671 static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
1673 MethodFlags flags = 0;
1675 if (mb.DeclaringType is TypeBuilder){
1676 MethodData method = (MethodData) builder_to_method [mb];
1677 if (method == null) {
1678 // FIXME: implement Obsolete attribute on Property,
1679 // Indexer and Event.
1683 return method.GetMethodFlags (loc);
1686 object [] attrs = mb.GetCustomAttributes (true);
1687 foreach (object ta in attrs){
1688 if (!(ta is System.Attribute)){
1689 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
1692 System.Attribute a = (System.Attribute) ta;
1693 if (a.TypeId == TypeManager.obsolete_attribute_type){
1694 ObsoleteAttribute oa = (ObsoleteAttribute) a;
1696 string method_desc = TypeManager.CSharpSignature (mb);
1699 Report.Error (619, loc, "Method `" + method_desc +
1700 "' is obsolete: `" + oa.Message + "'");
1701 return MethodFlags.IsObsoleteError;
1703 Report.Warning (618, loc, "Method `" + method_desc +
1704 "' is obsolete: `" + oa.Message + "'");
1706 flags |= MethodFlags.IsObsolete;
1712 // Skip over conditional code.
1714 if (a.TypeId == TypeManager.conditional_attribute_type){
1715 ConditionalAttribute ca = (ConditionalAttribute) a;
1717 if (RootContext.AllDefines [ca.ConditionString] == null)
1718 flags |= MethodFlags.ShouldIgnore;
1725 #region MemberLookup implementation
1728 // Name of the member
1730 static string closure_name;
1733 // Whether we allow private members in the result (since FindMembers
1734 // uses NonPublic for both protected and private), we need to distinguish.
1736 static bool closure_private_ok;
1739 // Who is invoking us and which type is being queried currently.
1741 static Type closure_invocation_type;
1742 static Type closure_queried_type;
1745 // The assembly that defines the type is that is calling us
1747 static Assembly closure_invocation_assembly;
1750 // This filter filters by name + whether it is ok to include private
1751 // members in the search
1753 static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1756 // Hack: we know that the filter criteria will always be in the `closure'
1760 if (m.Name != closure_name)
1764 // Ugly: we need to find out the type of `m', and depending
1765 // on this, tell whether we accept or not
1767 if (m is MethodBase){
1768 MethodBase mb = (MethodBase) m;
1769 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1771 if (ma == MethodAttributes.Private)
1772 return closure_private_ok;
1775 // FamAndAssem requires that we not only derivate, but we are on the
1778 if (ma == MethodAttributes.FamANDAssem){
1779 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1783 // FamORAssem, Family and Public:
1787 if (m is FieldInfo){
1788 FieldInfo fi = (FieldInfo) m;
1789 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
1791 if (fa == FieldAttributes.Private)
1792 return closure_private_ok;
1795 // FamAndAssem requires that we not only derivate, but we are on the
1798 if (fa == FieldAttributes.FamANDAssem){
1799 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
1802 // FamORAssem, Family and Public:
1807 // EventInfos and PropertyInfos, return true
1812 static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
1815 // Looks up a member called `name' in the `queried_type'. This lookup
1816 // is done by code that is contained in the definition for `invocation_type'.
1818 // The binding flags are `bf' and the kind of members being looked up are `mt'
1820 // Returns an array of a single element for everything but Methods/Constructors
1821 // that might return multiple matches.
1823 public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type,
1824 MemberTypes mt, BindingFlags original_bf, string name)
1826 BindingFlags bf = original_bf;
1828 ArrayList method_list = null;
1829 Type current_type = queried_type;
1830 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
1832 bool always_ok_flag = false;
1834 closure_name = name;
1835 closure_invocation_type = invocation_type;
1836 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
1839 // If we are a nested class, we always have access to our container
1842 if (invocation_type != null){
1843 string invocation_name = invocation_type.FullName;
1844 if (invocation_name.IndexOf ('+') != -1){
1845 string container = queried_type.FullName + "+";
1846 int container_length = container.Length;
1848 if (invocation_name.Length > container_length){
1849 string shared = invocation_name.Substring (0, container_length);
1851 if (shared == container)
1852 always_ok_flag = true;
1861 // `NonPublic' is lame, because it includes both protected and
1862 // private methods, so we need to control this behavior by
1863 // explicitly tracking if a private method is ok or not.
1865 // The possible cases are:
1866 // public, private and protected (internal does not come into the
1869 if (invocation_type != null){
1870 if (invocation_type == current_type){
1873 private_ok = always_ok_flag;
1875 if (private_ok || invocation_type.IsSubclassOf (current_type))
1876 bf = original_bf | BindingFlags.NonPublic;
1879 bf = original_bf & ~BindingFlags.NonPublic;
1882 closure_private_ok = private_ok;
1883 closure_queried_type = current_type;
1885 mi = TypeManager.FindMembers (
1886 current_type, mt, bf | BindingFlags.DeclaredOnly,
1887 FilterWithClosure_delegate, name);
1889 if (current_type == TypeManager.object_type)
1892 current_type = current_type.BaseType;
1895 // This happens with interfaces, they have a null
1896 // basetype. Look members up in the Object class.
1898 if (current_type == null)
1899 current_type = TypeManager.object_type;
1905 int count = mi.Length;
1911 // Events and types are returned by both `static' and `instance'
1912 // searches, which means that our above FindMembers will
1913 // return two copies of the same.
1915 if (count == 1 && !(mi [0] is MethodBase)){
1920 // Multiple properties: we query those just to find out the indexer
1923 if (mi [0] is PropertyInfo)
1927 // We found methods, turn the search into "method scan"
1931 method_list = CopyNewMethods (method_list, mi);
1932 mt &= (MemberTypes.Method | MemberTypes.Constructor);
1933 } while (searching);
1935 if (method_list != null && method_list.Count > 0)
1936 return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
1939 // Interfaces do not list members they inherit, so we have to
1942 if (!queried_type.IsInterface)
1945 if (queried_type.IsArray)
1946 queried_type = TypeManager.array_type;
1948 Type [] ifaces = GetInterfaces (queried_type);
1952 foreach (Type itype in ifaces){
1955 x = MemberLookup (null, itype, mt, bf, name);