2 // System.Reflection.MonoGenericClass
4 // Sean MacIsaac (macisaac@ximian.com)
5 // Paolo Molaro (lupus@ximian.com)
6 // Patrik Torstensson (patrik.torstensson@labs2.com)
8 // (C) 2001 Ximian, Inc.
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Globalization;
39 using System.Runtime.Serialization;
41 #if NET_2_0 || BOOTSTRAP_NET_2_0
43 namespace System.Reflection
46 * MonoGenericClass represents an instantiation of a generic TypeBuilder. MS
47 * calls this class TypeBuilderInstantiation (a much better name). MS returns
48 * NotImplementedException for many of the methods but we can't do that as gmcs
51 internal class MonoGenericClass : MonoType
53 #region Keep in sync with object-internals.h
54 #pragma warning disable 649
55 internal TypeBuilder generic_type;
56 Type[] type_arguments;
58 #pragma warning restore 649
61 Hashtable fields, ctors, methods;
64 internal MonoGenericClass ()
67 // this should not be used
68 throw new InvalidOperationException ();
71 internal MonoGenericClass (TypeBuilder tb, Type[] args) : base (null)
73 this.generic_type = tb;
74 this.type_arguments = args;
77 [MethodImplAttribute(MethodImplOptions.InternalCall)]
78 extern void initialize (MethodInfo[] methods, ConstructorInfo[] ctors, FieldInfo[] fields, PropertyInfo[] properties, EventInfo[] events);
80 [MethodImplAttribute(MethodImplOptions.InternalCall)]
81 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
83 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
84 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
91 MonoGenericClass parent = GetParentType () as MonoGenericClass;
94 EventInfo[] events = generic_type.GetEvents_internal (flags);
95 event_count = events.Length;
97 initialize (generic_type.GetMethods (flags),
98 generic_type.GetConstructorsInternal (flags),
99 generic_type.GetFields (flags),
100 generic_type.GetProperties (flags),
106 Type GetParentType ()
108 return InflateType (generic_type.BaseType);
111 internal Type InflateType (Type type)
115 if (!type.IsGenericParameter && !type.ContainsGenericParameters)
117 if (type.IsGenericParameter) {
118 if (type.DeclaringMethod == null)
119 return type_arguments [type.GenericParameterPosition];
123 return InflateType (type.GetElementType ()).MakePointerType ();
125 return InflateType (type.GetElementType ()).MakeByRefType ();
127 if (type.GetArrayRank () > 1)
128 return InflateType (type.GetElementType ()).MakeArrayType (type.GetArrayRank ());
129 if (type.ToString ().EndsWith ("[*]")) /*FIXME, the reflection API doesn't offer a way around this*/
130 return InflateType (type.GetElementType ()).MakeArrayType (1);
131 return InflateType (type.GetElementType ()).MakeArrayType ();
134 Type[] args = type.GetGenericArguments ();
135 for (int i = 0; i < args.Length; ++i)
136 args [i] = InflateType (args [i]);
138 Type gtd = type.IsGenericTypeDefinition ? type : type.GetGenericTypeDefinition ();
139 return gtd.MakeGenericType (args);
142 public override Type BaseType {
144 Type parent = GetParentType ();
145 return parent != null ? parent : generic_type.BaseType;
149 Type[] GetInterfacesInternal ()
151 if (generic_type.interfaces == null)
153 Type[] res = new Type [generic_type.interfaces.Length];
154 for (int i = 0; i < res.Length; ++i)
155 res [i] = InflateType (generic_type.interfaces [i]);
159 public override Type[] GetInterfaces ()
161 if (!generic_type.IsCompilerContext)
162 throw new NotSupportedException ();
163 return GetInterfacesInternal ();
166 protected override bool IsValueTypeImpl ()
168 return generic_type.IsValueType;
171 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
175 if (!(fromNoninstanciated is MethodBuilder))
176 throw new InvalidOperationException ("Inflating non MethodBuilder objects is not supported: " + fromNoninstanciated.GetType ());
178 if (fromNoninstanciated is MethodBuilder) {
179 MethodBuilder mb = (MethodBuilder)fromNoninstanciated;
181 // FIXME: We can't yet handle creating generic instantiations of
182 // MethodOnTypeBuilderInst objects
183 // Also, mono_image_get_method_on_inst_token () can't handle generic
185 if (!mb.IsGenericMethodDefinition) {
187 methods = new Hashtable ();
188 if (!methods.ContainsKey (mb))
189 methods [mb] = new MethodOnTypeBuilderInst (this, mb);
190 return (MethodInfo)methods [mb];
194 return GetCorrespondingInflatedMethod (fromNoninstanciated);
197 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
201 if (!(fromNoninstanciated is ConstructorBuilder))
202 throw new InvalidOperationException ("Inflating non ConstructorBuilder objects is not supported: " + fromNoninstanciated.GetType ());
204 ConstructorBuilder cb = (ConstructorBuilder)fromNoninstanciated;
206 ctors = new Hashtable ();
207 if (!ctors.ContainsKey (cb))
208 ctors [cb] = new ConstructorOnTypeBuilderInst (this, cb);
209 return (ConstructorInfo)ctors [cb];
212 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
216 if (!(fromNoninstanciated is FieldBuilder))
217 throw new InvalidOperationException ("Inflating non FieldBuilder objects is not supported: " + fromNoninstanciated.GetType ());
219 FieldBuilder fb = (FieldBuilder)fromNoninstanciated;
221 fields = new Hashtable ();
222 if (!fields.ContainsKey (fb))
223 fields [fb] = new FieldOnTypeBuilderInst (this, fb);
224 return (FieldInfo)fields [fb];
227 public override MethodInfo[] GetMethods (BindingFlags bf)
229 if (!generic_type.IsCompilerContext)
230 throw new NotSupportedException ();
232 ArrayList l = new ArrayList ();
235 // Walk up our class hierarchy and retrieve methods from our
239 Type current_type = this;
241 MonoGenericClass gi = current_type as MonoGenericClass;
243 l.AddRange (gi.GetMethodsInternal (bf, this));
244 else if (current_type is TypeBuilder)
245 l.AddRange (current_type.GetMethods (bf));
247 // If we encounter a `MonoType', its
248 // GetMethodsByName() will return all the methods
249 // from its parent type(s), so we can stop here.
250 MonoType mt = (MonoType) current_type;
251 l.AddRange (mt.GetMethodsByName (null, bf, false, this));
255 if ((bf & BindingFlags.DeclaredOnly) != 0)
257 current_type = current_type.BaseType;
258 } while (current_type != null);
260 MethodInfo[] result = new MethodInfo [l.Count];
265 MethodInfo[] GetMethodsInternal (BindingFlags bf, MonoGenericClass reftype)
267 if (generic_type.num_methods == 0)
268 return new MethodInfo [0];
270 ArrayList l = new ArrayList ();
272 MethodAttributes mattrs;
277 for (int i = 0; i < generic_type.num_methods; ++i) {
278 MethodInfo c = generic_type.methods [i];
281 mattrs = c.Attributes;
282 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
283 if ((bf & BindingFlags.Public) != 0)
286 if ((bf & BindingFlags.NonPublic) != 0)
292 if ((mattrs & MethodAttributes.Static) != 0) {
293 if ((bf & BindingFlags.Static) != 0)
296 if ((bf & BindingFlags.Instance) != 0)
301 c = TypeBuilder.GetMethod (this, c);
305 MethodInfo[] result = new MethodInfo [l.Count];
310 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
312 if (!generic_type.IsCompilerContext)
313 throw new NotSupportedException ();
315 ArrayList l = new ArrayList ();
317 Type current_type = this;
319 MonoGenericClass gi = current_type as MonoGenericClass;
321 l.AddRange (gi.GetConstructorsInternal (bf, this));
322 else if (current_type is TypeBuilder)
323 l.AddRange (current_type.GetConstructors (bf));
325 MonoType mt = (MonoType) current_type;
326 l.AddRange (mt.GetConstructors_internal (bf, this));
330 if ((bf & BindingFlags.DeclaredOnly) != 0)
332 current_type = current_type.BaseType;
333 } while (current_type != null);
335 ConstructorInfo[] result = new ConstructorInfo [l.Count];
340 ConstructorInfo[] GetConstructorsInternal (BindingFlags bf, MonoGenericClass reftype)
342 if (generic_type.ctors == null)
343 return new ConstructorInfo [0];
345 ArrayList l = new ArrayList ();
347 MethodAttributes mattrs;
351 for (int i = 0; i < generic_type.ctors.Length; i++) {
352 ConstructorInfo c = generic_type.ctors [i];
355 mattrs = c.Attributes;
356 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
357 if ((bf & BindingFlags.Public) != 0)
360 if ((bf & BindingFlags.NonPublic) != 0)
366 if ((mattrs & MethodAttributes.Static) != 0) {
367 if ((bf & BindingFlags.Static) != 0)
370 if ((bf & BindingFlags.Instance) != 0)
375 l.Add (TypeBuilder.GetConstructor (this, c));
378 ConstructorInfo[] result = new ConstructorInfo [l.Count];
383 public override FieldInfo[] GetFields (BindingFlags bf)
385 if (!generic_type.IsCompilerContext)
386 throw new NotSupportedException ();
388 ArrayList l = new ArrayList ();
390 Type current_type = this;
392 MonoGenericClass gi = current_type as MonoGenericClass;
394 l.AddRange (gi.GetFieldsInternal (bf, this));
395 else if (current_type is TypeBuilder)
396 l.AddRange (current_type.GetFields (bf));
398 MonoType mt = (MonoType) current_type;
399 l.AddRange (mt.GetFields_internal (bf, this));
403 if ((bf & BindingFlags.DeclaredOnly) != 0)
405 current_type = current_type.BaseType;
406 } while (current_type != null);
408 FieldInfo[] result = new FieldInfo [l.Count];
413 FieldInfo[] GetFieldsInternal (BindingFlags bf, MonoGenericClass reftype)
415 if (generic_type.num_fields == 0)
416 return new FieldInfo [0];
418 ArrayList l = new ArrayList ();
420 FieldAttributes fattrs;
424 for (int i = 0; i < generic_type.num_fields; i++) {
425 FieldInfo c = generic_type.fields [i];
428 fattrs = c.Attributes;
429 if ((fattrs & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) {
430 if ((bf & BindingFlags.Public) != 0)
433 if ((bf & BindingFlags.NonPublic) != 0)
439 if ((fattrs & FieldAttributes.Static) != 0) {
440 if ((bf & BindingFlags.Static) != 0)
443 if ((bf & BindingFlags.Instance) != 0)
448 l.Add (TypeBuilder.GetField (this, c));
451 FieldInfo[] result = new FieldInfo [l.Count];
456 public override PropertyInfo[] GetProperties (BindingFlags bf)
458 if (!generic_type.IsCompilerContext)
459 throw new NotSupportedException ();
461 ArrayList l = new ArrayList ();
463 Type current_type = this;
465 MonoGenericClass gi = current_type as MonoGenericClass;
467 l.AddRange (gi.GetPropertiesInternal (bf, this));
468 else if (current_type is TypeBuilder)
469 l.AddRange (current_type.GetProperties (bf));
471 MonoType mt = (MonoType) current_type;
472 l.AddRange (mt.GetPropertiesByName (null, bf, false, this));
476 if ((bf & BindingFlags.DeclaredOnly) != 0)
478 current_type = current_type.BaseType;
479 } while (current_type != null);
481 PropertyInfo[] result = new PropertyInfo [l.Count];
486 PropertyInfo[] GetPropertiesInternal (BindingFlags bf, MonoGenericClass reftype)
488 if (generic_type.properties == null)
489 return new PropertyInfo [0];
491 ArrayList l = new ArrayList ();
493 MethodAttributes mattrs;
498 foreach (PropertyInfo pinfo in generic_type.properties) {
500 accessor = pinfo.GetGetMethod (true);
501 if (accessor == null)
502 accessor = pinfo.GetSetMethod (true);
503 if (accessor == null)
505 mattrs = accessor.Attributes;
506 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
507 if ((bf & BindingFlags.Public) != 0)
510 if ((bf & BindingFlags.NonPublic) != 0)
516 if ((mattrs & MethodAttributes.Static) != 0) {
517 if ((bf & BindingFlags.Static) != 0)
520 if ((bf & BindingFlags.Instance) != 0)
525 l.Add (new PropertyOnTypeBuilderInst (reftype, pinfo));
527 PropertyInfo[] result = new PropertyInfo [l.Count];
532 public override EventInfo[] GetEvents (BindingFlags bf)
534 if (!generic_type.IsCompilerContext)
535 throw new NotSupportedException ();
537 ArrayList l = new ArrayList ();
539 Type current_type = this;
541 MonoGenericClass gi = current_type as MonoGenericClass;
543 l.AddRange (gi.GetEventsInternal (bf, this));
544 else if (current_type is TypeBuilder)
545 l.AddRange (current_type.GetEvents (bf));
547 MonoType mt = (MonoType) current_type;
548 l.AddRange (mt.GetEvents (bf));
552 if ((bf & BindingFlags.DeclaredOnly) != 0)
554 current_type = current_type.BaseType;
555 } while (current_type != null);
557 EventInfo[] result = new EventInfo [l.Count];
562 EventInfo[] GetEventsInternal (BindingFlags bf, MonoGenericClass reftype) {
563 if (generic_type.events == null)
564 return new EventInfo [0];
568 ArrayList l = new ArrayList ();
570 MethodAttributes mattrs;
573 for (int i = 0; i < event_count; ++i) {
574 EventBuilder ev = generic_type.events [i];
577 accessor = ev.add_method;
578 if (accessor == null)
579 accessor = ev.remove_method;
580 if (accessor == null)
582 mattrs = accessor.Attributes;
583 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
584 if ((bf & BindingFlags.Public) != 0)
587 if ((bf & BindingFlags.NonPublic) != 0)
593 if ((mattrs & MethodAttributes.Static) != 0) {
594 if ((bf & BindingFlags.Static) != 0)
597 if ((bf & BindingFlags.Instance) != 0)
602 l.Add (new EventOnTypeBuilderInst (this, ev));
604 EventInfo[] result = new EventInfo [l.Count];
609 public override Type[] GetNestedTypes (BindingFlags bf)
611 return generic_type.GetNestedTypes (bf);
614 public override bool IsAssignableFrom (Type c)
619 Type[] interfaces = GetInterfacesInternal ();
622 if (interfaces == null)
624 foreach (Type t in interfaces)
625 if (c.IsAssignableFrom (t))
630 Type parent = GetParentType ();
632 return c == typeof (object);
634 return c.IsAssignableFrom (parent);