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;
62 internal MonoGenericClass ()
65 // this should not be used
66 throw new InvalidOperationException ();
69 [MethodImplAttribute(MethodImplOptions.InternalCall)]
70 extern void initialize (MethodInfo[] methods, ConstructorInfo[] ctors, FieldInfo[] fields, PropertyInfo[] properties, EventInfo[] events);
72 [MethodImplAttribute(MethodImplOptions.InternalCall)]
73 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
75 [MethodImplAttribute(MethodImplOptions.InternalCall)]
76 extern EventInfo[] GetEvents_internal (Type reflected_type);
78 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
79 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
86 MonoGenericClass parent = GetParentType () as MonoGenericClass;
90 initialize (generic_type.GetMethods (flags),
91 generic_type.GetConstructors (flags),
92 generic_type.GetFields (flags),
93 generic_type.GetProperties (flags),
94 generic_type.GetEvents_internal (flags));
101 return InflateType (generic_type.BaseType);
104 [MethodImplAttribute(MethodImplOptions.InternalCall)]
105 private extern Type InflateType_internal (Type type);
107 internal Type InflateType (Type type)
111 if (!type.IsGenericParameter && !type.ContainsGenericParameters)
113 return InflateType_internal (type);
116 public override Type BaseType {
118 Type parent = GetParentType ();
119 return parent != null ? parent : generic_type.BaseType;
123 Type[] GetInterfacesInternal ()
125 if (generic_type.interfaces == null)
127 Type[] res = new Type [generic_type.interfaces.Length];
128 for (int i = 0; i < res.Length; ++i)
129 res [i] = InflateType (generic_type.interfaces [i]);
133 public override Type[] GetInterfaces ()
135 if (!generic_type.IsCompilerContext)
136 throw new NotSupportedException ();
137 return GetInterfacesInternal ();
140 protected override bool IsValueTypeImpl ()
142 return generic_type.IsValueType;
145 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
149 if (!(fromNoninstanciated is MethodBuilder))
150 throw new InvalidOperationException ("Inflating non MethodBuilder objects is not supported: " + fromNoninstanciated.GetType ());
152 if (fromNoninstanciated is MethodBuilder) {
153 MethodBuilder mb = (MethodBuilder)fromNoninstanciated;
155 // FIXME: We can't yet handle creating generic instantiations of
156 // MethodOnTypeBuilderInst objects
157 // Also, mono_image_get_method_on_inst_token () can't handle generic
159 if (!mb.IsGenericMethodDefinition) {
161 methods = new Hashtable ();
162 if (!methods.ContainsKey (mb))
163 methods [mb] = new MethodOnTypeBuilderInst (this, mb);
164 return (MethodInfo)methods [mb];
168 return GetCorrespondingInflatedMethod (fromNoninstanciated);
171 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
175 if (!(fromNoninstanciated is ConstructorBuilder))
176 throw new InvalidOperationException ("Inflating non ConstructorBuilder objects is not supported: " + fromNoninstanciated.GetType ());
178 ConstructorBuilder cb = (ConstructorBuilder)fromNoninstanciated;
180 ctors = new Hashtable ();
181 if (!ctors.ContainsKey (cb))
182 ctors [cb] = new ConstructorOnTypeBuilderInst (this, cb);
183 return (ConstructorInfo)ctors [cb];
186 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
190 if (!(fromNoninstanciated is FieldBuilder))
191 throw new InvalidOperationException ("Inflating non FieldBuilder objects is not supported: " + fromNoninstanciated.GetType ());
193 FieldBuilder fb = (FieldBuilder)fromNoninstanciated;
195 fields = new Hashtable ();
196 if (!fields.ContainsKey (fb))
197 fields [fb] = new FieldOnTypeBuilderInst (this, fb);
198 return (FieldInfo)fields [fb];
201 public override MethodInfo[] GetMethods (BindingFlags bf)
203 if (!generic_type.IsCompilerContext)
204 throw new NotSupportedException ();
206 ArrayList l = new ArrayList ();
209 // Walk up our class hierarchy and retrieve methods from our
213 Type current_type = this;
215 MonoGenericClass gi = current_type as MonoGenericClass;
217 l.AddRange (gi.GetMethodsInternal (bf, this));
218 else if (current_type is TypeBuilder)
219 l.AddRange (current_type.GetMethods (bf));
221 // If we encounter a `MonoType', its
222 // GetMethodsByName() will return all the methods
223 // from its parent type(s), so we can stop here.
224 MonoType mt = (MonoType) current_type;
225 l.AddRange (mt.GetMethodsByName (null, bf, false, this));
229 if ((bf & BindingFlags.DeclaredOnly) != 0)
231 current_type = current_type.BaseType;
232 } while (current_type != null);
234 MethodInfo[] result = new MethodInfo [l.Count];
239 MethodInfo[] GetMethodsInternal (BindingFlags bf, MonoGenericClass reftype)
241 if (generic_type.num_methods == 0)
242 return new MethodInfo [0];
244 ArrayList l = new ArrayList ();
246 MethodAttributes mattrs;
251 for (int i = 0; i < generic_type.num_methods; ++i) {
252 MethodInfo c = generic_type.methods [i];
255 mattrs = c.Attributes;
256 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
257 if ((bf & BindingFlags.Public) != 0)
260 if ((bf & BindingFlags.NonPublic) != 0)
266 if ((mattrs & MethodAttributes.Static) != 0) {
267 if ((bf & BindingFlags.Static) != 0)
270 if ((bf & BindingFlags.Instance) != 0)
275 c = TypeBuilder.GetMethod (this, c);
279 MethodInfo[] result = new MethodInfo [l.Count];
284 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
286 if (!generic_type.IsCompilerContext)
287 throw new NotSupportedException ();
289 ArrayList l = new ArrayList ();
291 Type current_type = this;
293 MonoGenericClass gi = current_type as MonoGenericClass;
295 l.AddRange (gi.GetConstructorsInternal (bf, this));
296 else if (current_type is TypeBuilder)
297 l.AddRange (current_type.GetConstructors (bf));
299 MonoType mt = (MonoType) current_type;
300 l.AddRange (mt.GetConstructors_internal (bf, this));
304 if ((bf & BindingFlags.DeclaredOnly) != 0)
306 current_type = current_type.BaseType;
307 } while (current_type != null);
309 ConstructorInfo[] result = new ConstructorInfo [l.Count];
314 ConstructorInfo[] GetConstructorsInternal (BindingFlags bf, MonoGenericClass reftype)
316 if (generic_type.ctors == null)
317 return new ConstructorInfo [0];
319 ArrayList l = new ArrayList ();
321 MethodAttributes mattrs;
325 for (int i = 0; i < generic_type.ctors.Length; i++) {
326 ConstructorInfo c = generic_type.ctors [i];
329 mattrs = c.Attributes;
330 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
331 if ((bf & BindingFlags.Public) != 0)
334 if ((bf & BindingFlags.NonPublic) != 0)
340 if ((mattrs & MethodAttributes.Static) != 0) {
341 if ((bf & BindingFlags.Static) != 0)
344 if ((bf & BindingFlags.Instance) != 0)
349 l.Add (TypeBuilder.GetConstructor (this, c));
352 ConstructorInfo[] result = new ConstructorInfo [l.Count];
357 public override FieldInfo[] GetFields (BindingFlags bf)
359 if (!generic_type.IsCompilerContext)
360 throw new NotSupportedException ();
362 ArrayList l = new ArrayList ();
364 Type current_type = this;
366 MonoGenericClass gi = current_type as MonoGenericClass;
368 l.AddRange (gi.GetFieldsInternal (bf, this));
369 else if (current_type is TypeBuilder)
370 l.AddRange (current_type.GetFields (bf));
372 MonoType mt = (MonoType) current_type;
373 l.AddRange (mt.GetFields_internal (bf, this));
377 if ((bf & BindingFlags.DeclaredOnly) != 0)
379 current_type = current_type.BaseType;
380 } while (current_type != null);
382 FieldInfo[] result = new FieldInfo [l.Count];
387 FieldInfo[] GetFieldsInternal (BindingFlags bf, MonoGenericClass reftype)
389 if (generic_type.num_fields == 0)
390 return new FieldInfo [0];
392 ArrayList l = new ArrayList ();
394 FieldAttributes fattrs;
398 for (int i = 0; i < generic_type.num_fields; i++) {
399 FieldInfo c = generic_type.fields [i];
402 fattrs = c.Attributes;
403 if ((fattrs & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) {
404 if ((bf & BindingFlags.Public) != 0)
407 if ((bf & BindingFlags.NonPublic) != 0)
413 if ((fattrs & FieldAttributes.Static) != 0) {
414 if ((bf & BindingFlags.Static) != 0)
417 if ((bf & BindingFlags.Instance) != 0)
422 l.Add (TypeBuilder.GetField (this, c));
425 FieldInfo[] result = new FieldInfo [l.Count];
430 public override PropertyInfo[] GetProperties (BindingFlags bf)
432 if (!generic_type.IsCompilerContext)
433 throw new NotSupportedException ();
435 ArrayList l = new ArrayList ();
437 Type current_type = this;
439 MonoGenericClass gi = current_type as MonoGenericClass;
441 l.AddRange (gi.GetPropertiesInternal (bf, this));
442 else if (current_type is TypeBuilder)
443 l.AddRange (current_type.GetProperties (bf));
445 MonoType mt = (MonoType) current_type;
446 l.AddRange (mt.GetPropertiesByName (null, bf, false, this));
450 if ((bf & BindingFlags.DeclaredOnly) != 0)
452 current_type = current_type.BaseType;
453 } while (current_type != null);
455 PropertyInfo[] result = new PropertyInfo [l.Count];
460 PropertyInfo[] GetPropertiesInternal (BindingFlags bf, MonoGenericClass reftype)
462 if (generic_type.properties == null)
463 return new PropertyInfo [0];
465 ArrayList l = new ArrayList ();
467 MethodAttributes mattrs;
472 foreach (PropertyInfo pinfo in generic_type.properties) {
474 accessor = pinfo.GetGetMethod (true);
475 if (accessor == null)
476 accessor = pinfo.GetSetMethod (true);
477 if (accessor == null)
479 mattrs = accessor.Attributes;
480 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
481 if ((bf & BindingFlags.Public) != 0)
484 if ((bf & BindingFlags.NonPublic) != 0)
490 if ((mattrs & MethodAttributes.Static) != 0) {
491 if ((bf & BindingFlags.Static) != 0)
494 if ((bf & BindingFlags.Instance) != 0)
499 l.Add (new PropertyOnTypeBuilderInst (reftype, pinfo));
501 PropertyInfo[] result = new PropertyInfo [l.Count];
506 public override EventInfo[] GetEvents (BindingFlags bf)
508 if (!generic_type.IsCompilerContext)
509 throw new NotSupportedException ();
511 ArrayList l = new ArrayList ();
513 Type current_type = this;
515 MonoGenericClass gi = current_type as MonoGenericClass;
517 l.AddRange (gi.GetEvents_impl (bf, this));
518 else if (current_type is TypeBuilder)
519 l.AddRange (current_type.GetEvents (bf));
521 MonoType mt = (MonoType) current_type;
522 l.AddRange (mt.GetEvents (bf));
526 if ((bf & BindingFlags.DeclaredOnly) != 0)
528 current_type = current_type.BaseType;
529 } while (current_type != null);
531 EventInfo[] result = new EventInfo [l.Count];
536 protected EventInfo[] GetEvents_impl (BindingFlags bf, Type reftype)
538 ArrayList l = new ArrayList ();
540 MethodAttributes mattrs;
545 EventInfo[] events = GetEvents_internal (reftype);
547 for (int i = 0; i < events.Length; i++) {
548 EventInfo c = events [i];
551 accessor = c.GetAddMethod (true);
552 if (accessor == null)
553 accessor = c.GetRemoveMethod (true);
554 if (accessor == null)
556 mattrs = accessor.Attributes;
557 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
558 if ((bf & BindingFlags.Public) != 0)
561 if ((bf & BindingFlags.NonPublic) != 0)
567 if ((mattrs & MethodAttributes.Static) != 0) {
568 if ((bf & BindingFlags.Static) != 0)
571 if ((bf & BindingFlags.Instance) != 0)
578 EventInfo[] result = new EventInfo [l.Count];
583 public override Type[] GetNestedTypes (BindingFlags bf)
585 return generic_type.GetNestedTypes (bf);
588 public override bool IsAssignableFrom (Type c)
593 Type[] interfaces = GetInterfacesInternal ();
596 if (interfaces == null)
598 foreach (Type t in interfaces)
599 if (c.IsAssignableFrom (t))
604 Type parent = GetParentType ();
606 return c == typeof (object);
608 return c.IsAssignableFrom (parent);