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;
57 #pragma warning restore 649
60 Hashtable fields, ctors, methods;
63 internal MonoGenericClass ()
66 // this should not be used
67 throw new InvalidOperationException ();
70 [MethodImplAttribute(MethodImplOptions.InternalCall)]
71 extern void initialize (MethodInfo[] methods, ConstructorInfo[] ctors, FieldInfo[] fields, PropertyInfo[] properties, EventInfo[] events);
73 [MethodImplAttribute(MethodImplOptions.InternalCall)]
74 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
76 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
77 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
84 MonoGenericClass parent = GetParentType () as MonoGenericClass;
88 EventInfo[] events = generic_type.GetEvents_internal (flags);
89 event_count = events.Length;
91 initialize (generic_type.GetMethods (flags),
92 generic_type.GetConstructors (flags),
93 generic_type.GetFields (flags),
94 generic_type.GetProperties (flags),
100 Type GetParentType ()
102 return InflateType (generic_type.BaseType);
105 [MethodImplAttribute(MethodImplOptions.InternalCall)]
106 private extern Type InflateType_internal (Type type);
108 internal Type InflateType (Type type)
112 if (!type.IsGenericParameter && !type.ContainsGenericParameters)
114 return InflateType_internal (type);
117 public override Type BaseType {
119 Type parent = GetParentType ();
120 return parent != null ? parent : generic_type.BaseType;
124 Type[] GetInterfacesInternal ()
126 if (generic_type.interfaces == null)
128 Type[] res = new Type [generic_type.interfaces.Length];
129 for (int i = 0; i < res.Length; ++i)
130 res [i] = InflateType (generic_type.interfaces [i]);
134 public override Type[] GetInterfaces ()
136 if (!generic_type.IsCompilerContext)
137 throw new NotSupportedException ();
138 return GetInterfacesInternal ();
141 protected override bool IsValueTypeImpl ()
143 return generic_type.IsValueType;
146 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
150 if (!(fromNoninstanciated is MethodBuilder))
151 throw new InvalidOperationException ("Inflating non MethodBuilder objects is not supported: " + fromNoninstanciated.GetType ());
153 if (fromNoninstanciated is MethodBuilder) {
154 MethodBuilder mb = (MethodBuilder)fromNoninstanciated;
156 // FIXME: We can't yet handle creating generic instantiations of
157 // MethodOnTypeBuilderInst objects
158 // Also, mono_image_get_method_on_inst_token () can't handle generic
160 if (!mb.IsGenericMethodDefinition) {
162 methods = new Hashtable ();
163 if (!methods.ContainsKey (mb))
164 methods [mb] = new MethodOnTypeBuilderInst (this, mb);
165 return (MethodInfo)methods [mb];
169 return GetCorrespondingInflatedMethod (fromNoninstanciated);
172 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
176 if (!(fromNoninstanciated is ConstructorBuilder))
177 throw new InvalidOperationException ("Inflating non ConstructorBuilder objects is not supported: " + fromNoninstanciated.GetType ());
179 ConstructorBuilder cb = (ConstructorBuilder)fromNoninstanciated;
181 ctors = new Hashtable ();
182 if (!ctors.ContainsKey (cb))
183 ctors [cb] = new ConstructorOnTypeBuilderInst (this, cb);
184 return (ConstructorInfo)ctors [cb];
187 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
191 if (fromNoninstanciated is FieldOnTypeBuilderInst && generic_type.IsCompilerContext) {
192 FieldOnTypeBuilderInst finst = (FieldOnTypeBuilderInst)fromNoninstanciated;
193 fromNoninstanciated = finst.fb;
196 if (!(fromNoninstanciated is FieldBuilder))
197 throw new InvalidOperationException ("Inflating non FieldBuilder objects is not supported: " + fromNoninstanciated.GetType ());
199 FieldBuilder fb = (FieldBuilder)fromNoninstanciated;
201 fields = new Hashtable ();
202 if (!fields.ContainsKey (fb))
203 fields [fb] = new FieldOnTypeBuilderInst (this, fb);
204 return (FieldInfo)fields [fb];
207 public override MethodInfo[] GetMethods (BindingFlags bf)
209 if (!generic_type.IsCompilerContext)
210 throw new NotSupportedException ();
212 ArrayList l = new ArrayList ();
215 // Walk up our class hierarchy and retrieve methods from our
219 Type current_type = this;
221 MonoGenericClass gi = current_type as MonoGenericClass;
223 l.AddRange (gi.GetMethodsInternal (bf, this));
224 else if (current_type is TypeBuilder)
225 l.AddRange (current_type.GetMethods (bf));
227 // If we encounter a `MonoType', its
228 // GetMethodsByName() will return all the methods
229 // from its parent type(s), so we can stop here.
230 MonoType mt = (MonoType) current_type;
231 l.AddRange (mt.GetMethodsByName (null, bf, false, this));
235 if ((bf & BindingFlags.DeclaredOnly) != 0)
237 current_type = current_type.BaseType;
238 } while (current_type != null);
240 MethodInfo[] result = new MethodInfo [l.Count];
245 MethodInfo[] GetMethodsInternal (BindingFlags bf, MonoGenericClass reftype)
247 if (generic_type.num_methods == 0)
248 return new MethodInfo [0];
250 ArrayList l = new ArrayList ();
252 MethodAttributes mattrs;
257 for (int i = 0; i < generic_type.num_methods; ++i) {
258 MethodInfo c = generic_type.methods [i];
261 mattrs = c.Attributes;
262 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
263 if ((bf & BindingFlags.Public) != 0)
266 if ((bf & BindingFlags.NonPublic) != 0)
272 if ((mattrs & MethodAttributes.Static) != 0) {
273 if ((bf & BindingFlags.Static) != 0)
276 if ((bf & BindingFlags.Instance) != 0)
281 c = TypeBuilder.GetMethod (this, c);
285 MethodInfo[] result = new MethodInfo [l.Count];
290 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
292 if (!generic_type.IsCompilerContext)
293 throw new NotSupportedException ();
295 ArrayList l = new ArrayList ();
297 Type current_type = this;
299 MonoGenericClass gi = current_type as MonoGenericClass;
301 l.AddRange (gi.GetConstructorsInternal (bf, this));
302 else if (current_type is TypeBuilder)
303 l.AddRange (current_type.GetConstructors (bf));
305 MonoType mt = (MonoType) current_type;
306 l.AddRange (mt.GetConstructors_internal (bf, this));
310 if ((bf & BindingFlags.DeclaredOnly) != 0)
312 current_type = current_type.BaseType;
313 } while (current_type != null);
315 ConstructorInfo[] result = new ConstructorInfo [l.Count];
320 ConstructorInfo[] GetConstructorsInternal (BindingFlags bf, MonoGenericClass reftype)
322 if (generic_type.ctors == null)
323 return new ConstructorInfo [0];
325 ArrayList l = new ArrayList ();
327 MethodAttributes mattrs;
331 for (int i = 0; i < generic_type.ctors.Length; i++) {
332 ConstructorInfo c = generic_type.ctors [i];
335 mattrs = c.Attributes;
336 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
337 if ((bf & BindingFlags.Public) != 0)
340 if ((bf & BindingFlags.NonPublic) != 0)
346 if ((mattrs & MethodAttributes.Static) != 0) {
347 if ((bf & BindingFlags.Static) != 0)
350 if ((bf & BindingFlags.Instance) != 0)
355 l.Add (TypeBuilder.GetConstructor (this, c));
358 ConstructorInfo[] result = new ConstructorInfo [l.Count];
363 public override FieldInfo[] GetFields (BindingFlags bf)
365 if (!generic_type.IsCompilerContext)
366 throw new NotSupportedException ();
368 ArrayList l = new ArrayList ();
370 Type current_type = this;
372 MonoGenericClass gi = current_type as MonoGenericClass;
374 l.AddRange (gi.GetFieldsInternal (bf, this));
375 else if (current_type is TypeBuilder)
376 l.AddRange (current_type.GetFields (bf));
378 MonoType mt = (MonoType) current_type;
379 l.AddRange (mt.GetFields_internal (bf, this));
383 if ((bf & BindingFlags.DeclaredOnly) != 0)
385 current_type = current_type.BaseType;
386 } while (current_type != null);
388 FieldInfo[] result = new FieldInfo [l.Count];
393 FieldInfo[] GetFieldsInternal (BindingFlags bf, MonoGenericClass reftype)
395 if (generic_type.num_fields == 0)
396 return new FieldInfo [0];
398 ArrayList l = new ArrayList ();
400 FieldAttributes fattrs;
404 for (int i = 0; i < generic_type.num_fields; i++) {
405 FieldInfo c = generic_type.fields [i];
408 fattrs = c.Attributes;
409 if ((fattrs & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) {
410 if ((bf & BindingFlags.Public) != 0)
413 if ((bf & BindingFlags.NonPublic) != 0)
419 if ((fattrs & FieldAttributes.Static) != 0) {
420 if ((bf & BindingFlags.Static) != 0)
423 if ((bf & BindingFlags.Instance) != 0)
428 l.Add (TypeBuilder.GetField (this, c));
431 FieldInfo[] result = new FieldInfo [l.Count];
436 public override PropertyInfo[] GetProperties (BindingFlags bf)
438 if (!generic_type.IsCompilerContext)
439 throw new NotSupportedException ();
441 ArrayList l = new ArrayList ();
443 Type current_type = this;
445 MonoGenericClass gi = current_type as MonoGenericClass;
447 l.AddRange (gi.GetPropertiesInternal (bf, this));
448 else if (current_type is TypeBuilder)
449 l.AddRange (current_type.GetProperties (bf));
451 MonoType mt = (MonoType) current_type;
452 l.AddRange (mt.GetPropertiesByName (null, bf, false, this));
456 if ((bf & BindingFlags.DeclaredOnly) != 0)
458 current_type = current_type.BaseType;
459 } while (current_type != null);
461 PropertyInfo[] result = new PropertyInfo [l.Count];
466 PropertyInfo[] GetPropertiesInternal (BindingFlags bf, MonoGenericClass reftype)
468 if (generic_type.properties == null)
469 return new PropertyInfo [0];
471 ArrayList l = new ArrayList ();
473 MethodAttributes mattrs;
478 foreach (PropertyInfo pinfo in generic_type.properties) {
480 accessor = pinfo.GetGetMethod (true);
481 if (accessor == null)
482 accessor = pinfo.GetSetMethod (true);
483 if (accessor == null)
485 mattrs = accessor.Attributes;
486 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
487 if ((bf & BindingFlags.Public) != 0)
490 if ((bf & BindingFlags.NonPublic) != 0)
496 if ((mattrs & MethodAttributes.Static) != 0) {
497 if ((bf & BindingFlags.Static) != 0)
500 if ((bf & BindingFlags.Instance) != 0)
505 l.Add (new PropertyOnTypeBuilderInst (reftype, pinfo));
507 PropertyInfo[] result = new PropertyInfo [l.Count];
512 public override EventInfo[] GetEvents (BindingFlags bf)
514 if (!generic_type.IsCompilerContext)
515 throw new NotSupportedException ();
517 ArrayList l = new ArrayList ();
519 Type current_type = this;
521 MonoGenericClass gi = current_type as MonoGenericClass;
523 l.AddRange (gi.GetEventsInternal (bf, this));
524 else if (current_type is TypeBuilder)
525 l.AddRange (current_type.GetEvents (bf));
527 MonoType mt = (MonoType) current_type;
528 l.AddRange (mt.GetEvents (bf));
532 if ((bf & BindingFlags.DeclaredOnly) != 0)
534 current_type = current_type.BaseType;
535 } while (current_type != null);
537 EventInfo[] result = new EventInfo [l.Count];
542 EventInfo[] GetEventsInternal (BindingFlags bf, MonoGenericClass reftype) {
543 if (generic_type.events == null)
544 return new EventInfo [0];
548 ArrayList l = new ArrayList ();
550 MethodAttributes mattrs;
553 for (int i = 0; i < event_count; ++i) {
554 EventBuilder ev = generic_type.events [i];
557 accessor = ev.add_method;
558 if (accessor == null)
559 accessor = ev.remove_method;
560 if (accessor == null)
562 mattrs = accessor.Attributes;
563 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
564 if ((bf & BindingFlags.Public) != 0)
567 if ((bf & BindingFlags.NonPublic) != 0)
573 if ((mattrs & MethodAttributes.Static) != 0) {
574 if ((bf & BindingFlags.Static) != 0)
577 if ((bf & BindingFlags.Instance) != 0)
582 l.Add (new EventOnTypeBuilderInst (reftype, ev));
584 EventInfo[] result = new EventInfo [l.Count];
589 public override Type[] GetNestedTypes (BindingFlags bf)
591 return generic_type.GetNestedTypes (bf);
594 public override bool IsAssignableFrom (Type c)
599 Type[] interfaces = GetInterfacesInternal ();
602 if (interfaces == null)
604 foreach (Type t in interfaces)
605 if (c.IsAssignableFrom (t))
610 Type parent = GetParentType ();
612 return c == typeof (object);
614 return c.IsAssignableFrom (parent);