2 // typegen.cs: type generation
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
19 public class TypeManager {
21 // A list of core types that the compiler requires or uses
23 static public Type object_type;
24 static public Type value_type;
25 static public Type string_type;
26 static public Type int32_type;
27 static public Type uint32_type;
28 static public Type int64_type;
29 static public Type uint64_type;
30 static public Type float_type;
31 static public Type double_type;
32 static public Type char_type;
33 static public Type short_type;
34 static public Type decimal_type;
35 static public Type bool_type;
36 static public Type sbyte_type;
37 static public Type byte_type;
38 static public Type ushort_type;
39 static public Type enum_type;
40 static public Type delegate_type;
41 static public Type void_type;
42 static public Type enumeration_type;
43 static public Type array_type;
44 static public Type runtime_handle_type;
45 static public Type icloneable_type;
46 static public Type type_type;
47 static public Type ienumerator_type;
48 static public Type idisposable_type;
49 static public Type default_member_type;
50 static public Type iasyncresult_type;
51 static public Type asynccallback_type;
52 static public Type intptr_type;
53 static public Type monitor_type;
56 // These methods are called by code generated by the compiler
58 static public MethodInfo string_concat_string_string;
59 static public MethodInfo string_concat_object_object;
60 static public MethodInfo system_type_get_type_from_handle;
61 static public MethodInfo object_getcurrent_void;
62 static public MethodInfo bool_movenext_void;
63 static public MethodInfo void_dispose_void;
64 static public MethodInfo void_monitor_enter_object;
65 static public MethodInfo void_monitor_exit_object;
68 // Holds the Array of Assemblies that have been loaded
69 // (either because it is the default or the user used the
70 // -r command line option)
75 // Keeps a list of module builders. We used this to do lookups
76 // on the modulebuilder using GetType -- needed for arrays
81 // This is the type_cache from the assemblies to avoid
82 // hitting System.Reflection on every lookup.
87 // This is used to hotld the corresponding TypeContainer objects
88 // since we need this in FindMembers
90 Hashtable typecontainers;
93 // Keeps track of those types that are defined by the
99 // Keeps a mapping between TypeBuilders and their TypeContainers
101 static Hashtable builder_to_container;
104 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
105 // the arguments to the method
107 static Hashtable method_arguments;
109 static Hashtable builder_to_interface;
112 // Keeps track of delegate types
115 static Hashtable delegate_types;
117 public TypeManager ()
119 assemblies = new ArrayList ();
120 modules = new ArrayList ();
121 user_types = new ArrayList ();
122 types = new Hashtable ();
123 typecontainers = new Hashtable ();
124 builder_to_interface = new Hashtable ();
125 delegate_types = new Hashtable ();
128 static TypeManager ()
130 method_arguments = new Hashtable ();
131 builder_to_container = new Hashtable ();
132 type_interface_cache = new Hashtable ();
135 public void AddUserType (string name, TypeBuilder t)
141 public void AddUserType (string name, TypeBuilder t, TypeContainer tc)
143 AddUserType (name, t);
144 builder_to_container.Add (t, tc);
145 typecontainers.Add (name, tc);
148 public void AddDelegateType (string name, TypeBuilder t, Delegate del)
151 delegate_types.Add (t, del);
154 public void AddUserInterface (string name, TypeBuilder t, Interface i)
156 AddUserType (name, t);
157 builder_to_interface.Add (t, i);
161 // Returns the TypeContainer whose Type is `t' or null if there is no
162 // TypeContainer for `t' (ie, the Type comes from a library)
164 public static TypeContainer LookupTypeContainer (Type t)
166 return (TypeContainer) builder_to_container [t];
169 public Interface LookupInterface (Type t)
171 return (Interface) builder_to_interface [t];
174 public static Delegate LookupDelegate (Type t)
176 return (Delegate) delegate_types [t];
180 // Registers an assembly to load types from.
182 public void AddAssembly (Assembly a)
188 // Registers a module builder to lookup types from
190 public void AddModule (ModuleBuilder mb)
196 // Returns the Type associated with @name
198 public Type LookupType (string name)
203 // First lookup in user defined and cached values
206 t = (Type) types [name];
210 foreach (Assembly a in assemblies){
211 t = a.GetType (name);
219 foreach (ModuleBuilder mb in modules) {
220 t = mb.GetType (name);
231 // Returns the C# name of a type if possible, or the full type name otherwise
233 static public string CSharpName (Type t)
237 else if (t == uint32_type)
239 else if (t == int64_type)
241 else if (t == uint64_type)
243 else if (t == float_type)
245 else if (t == double_type)
247 else if (t == char_type)
249 else if (t == short_type)
251 else if (t == decimal_type)
253 else if (t == bool_type)
255 else if (t == sbyte_type)
257 else if (t == byte_type)
259 else if (t == short_type)
261 else if (t == ushort_type)
263 else if (t == string_type)
265 else if (t == object_type)
272 // Looks up a type, and aborts if it is not found. This is used
273 // by types required by the compiler
275 Type CoreLookupType (string name)
277 Type t = LookupType (name);
280 throw new Exception ("Can not find core type " + name);
286 // Returns the MethodInfo for a method named `name' defined
287 // in type `t' which takes arguments of types `args'
289 MethodInfo GetMethod (Type t, string name, Type [] args)
291 MethodInfo mi = t.GetMethod (name, args);
294 throw new Exception ("Can not find the core function `" + name + "'");
300 // The types have to be initialized after the initial
301 // population of the type has happened (for example, to
302 // bootstrap the corlib.dll
304 public void InitCoreTypes ()
306 object_type = CoreLookupType ("System.Object");
307 value_type = CoreLookupType ("System.ValueType");
308 string_type = CoreLookupType ("System.String");
309 int32_type = CoreLookupType ("System.Int32");
310 int64_type = CoreLookupType ("System.Int64");
311 uint32_type = CoreLookupType ("System.UInt32");
312 uint64_type = CoreLookupType ("System.UInt64");
313 float_type = CoreLookupType ("System.Single");
314 double_type = CoreLookupType ("System.Double");
315 byte_type = CoreLookupType ("System.Byte");
316 sbyte_type = CoreLookupType ("System.SByte");
317 char_type = CoreLookupType ("System.Char");
318 short_type = CoreLookupType ("System.Int16");
319 ushort_type = CoreLookupType ("System.UInt16");
320 decimal_type = CoreLookupType ("System.Decimal");
321 bool_type = CoreLookupType ("System.Boolean");
322 enum_type = CoreLookupType ("System.Enum");
323 delegate_type = CoreLookupType ("System.MulticastDelegate");
324 array_type = CoreLookupType ("System.Array");
325 void_type = CoreLookupType ("System.Void");
326 type_type = CoreLookupType ("System.Type");
328 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
329 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
330 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
331 icloneable_type = CoreLookupType ("System.ICloneable");
332 idisposable_type = CoreLookupType ("System.IDisposable");
333 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
334 asynccallback_type = CoreLookupType ("System.AsyncCallback");
335 monitor_type = CoreLookupType ("System.Threading.Monitor");
336 intptr_type = CoreLookupType ("System.IntPtr");
339 // Now load the default methods that we use.
341 Type [] string_string = { string_type, string_type };
342 Type [] object_object = { object_type, object_type };
343 Type [] runtime_type_handle = { runtime_handle_type };
344 Type [] void_arg = { };
345 Type [] object_arg = { object_type };
347 string_concat_string_string = GetMethod (
348 string_type, "Concat", string_string);
349 string_concat_object_object = GetMethod (
350 string_type, "Concat", object_object);
351 system_type_get_type_from_handle = GetMethod (
352 type_type, "GetTypeFromHandle", runtime_type_handle);
353 object_getcurrent_void = GetMethod (
354 ienumerator_type, "get_Current", void_arg);
355 bool_movenext_void = GetMethod (
356 ienumerator_type, "MoveNext", void_arg);
357 void_dispose_void = GetMethod (
358 idisposable_type, "Dispose", void_arg);
359 void_monitor_enter_object = GetMethod (
360 monitor_type, "Enter", object_arg);
361 void_monitor_exit_object = GetMethod (
362 monitor_type, "Exit", object_arg);
365 public MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
369 if (IsDelegateType (t))
372 Interface iface = (Interface) builder_to_interface [t];
375 return iface.FindMembers (mt, bf, filter, criteria);
377 tc = (TypeContainer) builder_to_container [t];
380 return t.FindMembers (mt, bf, filter, criteria);
382 return tc.FindMembers (mt, bf, filter, criteria);
386 public static bool IsBuiltinType (Type t)
388 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
389 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
390 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
391 t == sbyte_type || t == byte_type || t == ushort_type)
397 public static bool IsDelegateType (Type t)
399 Delegate del = (Delegate) delegate_types [t];
407 public static bool IsInterfaceType (Type t)
409 Interface iface = (Interface) builder_to_interface [t];
418 // Returns the User Defined Types
420 public ArrayList UserTypes {
426 public Hashtable TypeContainers {
428 return typecontainers;
432 static string GetSig (MethodBase mb)
434 if (mb is MethodBuilder || mb is ConstructorBuilder)
435 return mb.ReflectedType.FullName + ":" + mb;
437 return mb.MethodHandle.ToString ();
441 // Gigantic work around for stupidity in System.Reflection.Emit follows
443 // Since System.Reflection.Emit can not return MethodBase.GetParameters
444 // for anything which is dynamic, and we need this in a number of places,
445 // we register this information here, and use it afterwards.
447 static public void RegisterMethod (MethodBase mb, Type [] args)
452 method_arguments.Add (s, args);
456 // Returns the argument types for a method based on its methodbase
458 // For dynamic methods, we use the compiler provided types, for
459 // methods from existing assemblies we load them from GetParameters,
460 // and insert them into the cache
462 static public Type [] GetArgumentTypes (MethodBase mb)
464 string sig = GetSig (mb);
465 object o = method_arguments [sig];
467 if (method_arguments.Contains (sig))
468 return (Type []) method_arguments [sig];
470 ParameterInfo [] pi = mb.GetParameters ();
472 Type [] types = new Type [c];
474 for (int i = 0; i < c; i++)
475 types [i] = pi [i].ParameterType;
477 method_arguments.Add (sig, types);
482 static Hashtable properties;
484 static public void RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
486 if (properties == null)
487 properties = new Hashtable ();
489 properties.Add (pb, new DictionaryEntry (get, set));
492 static public MethodInfo [] GetAccessors (PropertyInfo pi)
496 if (pi is PropertyBuilder){
497 DictionaryEntry de = (DictionaryEntry) properties [pi];
499 ret = new MethodInfo [2];
500 ret [0] = (MethodInfo) de.Key;
501 ret [1] = (MethodInfo) de.Value;
505 return pi.GetAccessors ();
509 // The following is used to check if a given type implements an interface.
510 // The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
513 static Hashtable type_interface_cache;
515 public static bool ImplementsInterface (Type t, Type iface)
517 Type [] interfaces = (Type []) type_interface_cache [t];
519 if (interfaces == null) {
520 if (type_interface_cache.Contains (t))
523 interfaces = t.GetInterfaces ();
525 type_interface_cache [t] = interfaces;
528 if (interfaces == null)
531 for (int i = interfaces.Length; i > 0; ) {
533 if (interfaces [i] == iface)
542 // Returns the name of the indexer in a given type. The default
543 // is not always `Item'. The user can change this behaviour by
544 // using the DefaultMemberAttribute in the class.
546 // For example, the String class indexer is named `Chars' not `Item'
548 public static string IndexerPropertyName (Type t)
552 // FIXME: Replace with something that works around S.R.E failure
555 System.Attribute attr;
557 attr = System.Attribute.GetCustomAttribute (t, TypeManager.default_member_type);
561 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
563 return dma.MemberName;