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 protected 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 protected 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 FieldInfo GetCorrespondingInflatedField (string generic);
78 [MethodImplAttribute(MethodImplOptions.InternalCall)]
79 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
81 [MethodImplAttribute(MethodImplOptions.InternalCall)]
82 protected extern MethodInfo[] GetMethods_internal (Type reflected_type);
84 [MethodImplAttribute(MethodImplOptions.InternalCall)]
85 protected extern ConstructorInfo[] GetConstructors_internal (Type reflected_type);
87 [MethodImplAttribute(MethodImplOptions.InternalCall)]
88 protected extern FieldInfo[] GetFields_internal (Type reflected_type);
90 [MethodImplAttribute(MethodImplOptions.InternalCall)]
91 protected extern PropertyInfo[] GetProperties_internal (Type reflected_type);
93 [MethodImplAttribute(MethodImplOptions.InternalCall)]
94 protected extern EventInfo[] GetEvents_internal (Type reflected_type);
96 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
97 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
104 MonoGenericClass parent = GetParentType () as MonoGenericClass;
106 parent.initialize ();
108 initialize (generic_type.GetMethods (flags),
109 generic_type.GetConstructors (flags),
110 generic_type.GetFields (flags),
111 generic_type.GetProperties (flags),
112 generic_type.GetEvents_internal (flags));
117 [MethodImplAttribute(MethodImplOptions.InternalCall)]
118 protected extern Type GetParentType ();
120 [MethodImplAttribute(MethodImplOptions.InternalCall)]
121 private extern Type InflateType_internal (Type type);
123 internal Type InflateType (Type type)
127 if (!type.IsGenericParameter && !type.ContainsGenericParameters)
129 return InflateType_internal (type);
132 [MethodImplAttribute(MethodImplOptions.InternalCall)]
133 protected extern MonoGenericClass[] GetInterfaces_internal ();
135 public override Type BaseType {
137 Type parent = GetParentType ();
138 return parent != null ? parent : generic_type.BaseType;
142 public override Type[] GetInterfaces ()
144 return GetInterfaces_internal ();
147 protected override bool IsValueTypeImpl ()
149 return generic_type.IsValueType;
152 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
157 if (fromNoninstanciated is MethodOnTypeBuilderInst) {
158 MethodOnTypeBuilderInst mbinst = (MethodOnTypeBuilderInst)fromNoninstanciated;
159 if (((ModuleBuilder)mbinst.mb.Module).assemblyb.IsCompilerContext)
160 fromNoninstanciated = mbinst.mb;
162 throw new ArgumentException ("method declaring type is not the generic type definition of type", "method");
165 if (fromNoninstanciated is MethodBuilder) {
166 MethodBuilder mb = (MethodBuilder)fromNoninstanciated;
168 // FIXME: We can't yet handle creating generic instantiations of
169 // MethodOnTypeBuilderInst objects
170 // Also, mono_image_get_method_on_inst_token () can't handle generic
172 if (!mb.IsGenericMethodDefinition) {
174 methods = new Hashtable ();
175 if (!methods.ContainsKey (mb))
176 methods [mb] = new MethodOnTypeBuilderInst (this, mb);
177 return (MethodInfo)methods [mb];
182 return GetCorrespondingInflatedMethod (fromNoninstanciated);
185 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
190 if (fromNoninstanciated is ConstructorBuilder) {
191 ConstructorBuilder cb = (ConstructorBuilder)fromNoninstanciated;
193 ctors = new Hashtable ();
194 if (!ctors.ContainsKey (cb))
195 ctors [cb] = new ConstructorOnTypeBuilderInst (this, cb);
196 return (ConstructorInfo)ctors [cb];
200 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
203 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
208 if (fromNoninstanciated is FieldBuilder) {
209 FieldBuilder fb = (FieldBuilder)fromNoninstanciated;
211 fields = new Hashtable ();
212 if (!fields.ContainsKey (fb))
213 fields [fb] = new FieldOnTypeBuilderInst (this, fb);
214 return (FieldInfo)fields [fb];
217 return GetCorrespondingInflatedField (fromNoninstanciated.Name);
220 public override MethodInfo[] GetMethods (BindingFlags bf)
222 ArrayList l = new ArrayList ();
225 // Walk up our class hierarchy and retrieve methods from our
229 Type current_type = this;
231 MonoGenericClass gi = current_type as MonoGenericClass;
233 l.AddRange (gi.GetMethods_impl (bf, this));
234 else if (current_type is TypeBuilder)
235 l.AddRange (current_type.GetMethods (bf));
237 // If we encounter a `MonoType', its
238 // GetMethodsByName() will return all the methods
239 // from its parent type(s), so we can stop here.
240 MonoType mt = (MonoType) current_type;
241 l.AddRange (mt.GetMethodsByName (null, bf, false, this));
245 if ((bf & BindingFlags.DeclaredOnly) != 0)
247 current_type = current_type.BaseType;
248 } while (current_type != null);
250 MethodInfo[] result = new MethodInfo [l.Count];
255 protected MethodInfo[] GetMethods_impl (BindingFlags bf, Type reftype)
257 ArrayList l = new ArrayList ();
259 MethodAttributes mattrs;
263 MethodInfo[] methods = GetMethods_internal (reftype);
265 for (int i = 0; i < methods.Length; i++) {
266 MethodInfo c = methods [i];
269 mattrs = c.Attributes;
270 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
271 if ((bf & BindingFlags.Public) != 0)
274 if ((bf & BindingFlags.NonPublic) != 0)
280 if ((mattrs & MethodAttributes.Static) != 0) {
281 if ((bf & BindingFlags.Static) != 0)
284 if ((bf & BindingFlags.Instance) != 0)
291 MethodInfo[] result = new MethodInfo [l.Count];
296 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
298 ArrayList l = new ArrayList ();
300 Type current_type = this;
302 MonoGenericClass gi = current_type as MonoGenericClass;
304 l.AddRange (gi.GetConstructors_impl (bf, this));
305 else if (current_type is TypeBuilder)
306 l.AddRange (current_type.GetConstructors (bf));
308 MonoType mt = (MonoType) current_type;
309 l.AddRange (mt.GetConstructors_internal (bf, this));
313 if ((bf & BindingFlags.DeclaredOnly) != 0)
315 current_type = current_type.BaseType;
316 } while (current_type != null);
318 ConstructorInfo[] result = new ConstructorInfo [l.Count];
323 protected ConstructorInfo[] GetConstructors_impl (BindingFlags bf, Type reftype)
325 ArrayList l = new ArrayList ();
327 MethodAttributes mattrs;
331 ConstructorInfo[] ctors = GetConstructors_internal (reftype);
333 for (int i = 0; i < ctors.Length; i++) {
334 ConstructorInfo c = ctors [i];
337 mattrs = c.Attributes;
338 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
339 if ((bf & BindingFlags.Public) != 0)
342 if ((bf & BindingFlags.NonPublic) != 0)
348 if ((mattrs & MethodAttributes.Static) != 0) {
349 if ((bf & BindingFlags.Static) != 0)
352 if ((bf & BindingFlags.Instance) != 0)
360 ConstructorInfo[] result = new ConstructorInfo [l.Count];
365 public override FieldInfo[] GetFields (BindingFlags bf)
367 ArrayList l = new ArrayList ();
369 Type current_type = this;
371 MonoGenericClass gi = current_type as MonoGenericClass;
373 l.AddRange (gi.GetFields_impl (bf, this));
374 else if (current_type is TypeBuilder)
375 l.AddRange (current_type.GetFields (bf));
377 MonoType mt = (MonoType) current_type;
378 l.AddRange (mt.GetFields_internal (bf, this));
382 if ((bf & BindingFlags.DeclaredOnly) != 0)
384 current_type = current_type.BaseType;
385 } while (current_type != null);
387 FieldInfo[] result = new FieldInfo [l.Count];
392 protected FieldInfo[] GetFields_impl (BindingFlags bf, Type reftype)
394 ArrayList l = new ArrayList ();
396 FieldAttributes fattrs;
400 FieldInfo[] fields = GetFields_internal (reftype);
402 for (int i = 0; i < fields.Length; i++) {
403 FieldInfo c = fields [i];
406 fattrs = c.Attributes;
407 if ((fattrs & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) {
408 if ((bf & BindingFlags.Public) != 0)
411 if ((bf & BindingFlags.NonPublic) != 0)
417 if ((fattrs & FieldAttributes.Static) != 0) {
418 if ((bf & BindingFlags.Static) != 0)
421 if ((bf & BindingFlags.Instance) != 0)
428 FieldInfo[] result = new FieldInfo [l.Count];
433 public override PropertyInfo[] GetProperties (BindingFlags bf)
435 ArrayList l = new ArrayList ();
437 Type current_type = this;
439 MonoGenericClass gi = current_type as MonoGenericClass;
441 l.AddRange (gi.GetProperties_impl (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 protected PropertyInfo[] GetProperties_impl (BindingFlags bf, Type reftype)
462 ArrayList l = new ArrayList ();
464 MethodAttributes mattrs;
469 PropertyInfo[] properties = GetProperties_internal (reftype);
471 for (int i = 0; i < properties.Length; i++) {
472 PropertyInfo c = properties [i];
475 accessor = c.GetGetMethod (true);
476 if (accessor == null)
477 accessor = c.GetSetMethod (true);
478 if (accessor == null)
480 mattrs = accessor.Attributes;
481 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
482 if ((bf & BindingFlags.Public) != 0)
485 if ((bf & BindingFlags.NonPublic) != 0)
491 if ((mattrs & MethodAttributes.Static) != 0) {
492 if ((bf & BindingFlags.Static) != 0)
495 if ((bf & BindingFlags.Instance) != 0)
502 PropertyInfo[] result = new PropertyInfo [l.Count];
507 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
508 Binder binder, Type returnType,
510 ParameterModifier[] modifiers)
512 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
513 PropertyInfo [] props = GetProperties (bindingAttr);
516 for (int i = 0; i < props.Length; ++i) {
517 if (String.Compare (props [i].Name, name, ignoreCase) == 0) {
519 al = new ArrayList ();
526 props = (PropertyInfo[])al.ToArray (typeof (PropertyInfo));
528 int count = props.Length;
530 if (count == 1 && (types == null || types.Length == 0) &&
531 (returnType == null || returnType == props[0].PropertyType))
535 binder = Binder.DefaultBinder;
537 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
540 public override EventInfo[] GetEvents (BindingFlags bf)
542 ArrayList l = new ArrayList ();
544 Type current_type = this;
546 MonoGenericClass gi = current_type as MonoGenericClass;
548 l.AddRange (gi.GetEvents_impl (bf, this));
549 else if (current_type is TypeBuilder)
550 l.AddRange (current_type.GetEvents (bf));
552 MonoType mt = (MonoType) current_type;
553 l.AddRange (mt.GetEvents (bf));
557 if ((bf & BindingFlags.DeclaredOnly) != 0)
559 current_type = current_type.BaseType;
560 } while (current_type != null);
562 EventInfo[] result = new EventInfo [l.Count];
567 protected EventInfo[] GetEvents_impl (BindingFlags bf, Type reftype)
569 ArrayList l = new ArrayList ();
571 MethodAttributes mattrs;
576 EventInfo[] events = GetEvents_internal (reftype);
578 for (int i = 0; i < events.Length; i++) {
579 EventInfo c = events [i];
582 accessor = c.GetAddMethod (true);
583 if (accessor == null)
584 accessor = c.GetRemoveMethod (true);
585 if (accessor == null)
587 mattrs = accessor.Attributes;
588 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
589 if ((bf & BindingFlags.Public) != 0)
592 if ((bf & BindingFlags.NonPublic) != 0)
598 if ((mattrs & MethodAttributes.Static) != 0) {
599 if ((bf & BindingFlags.Static) != 0)
602 if ((bf & BindingFlags.Instance) != 0)
609 EventInfo[] result = new EventInfo [l.Count];
614 public override Type[] GetNestedTypes (BindingFlags bf)
616 return generic_type.GetNestedTypes (bf);
619 public override bool IsAssignableFrom (Type c)
624 MonoGenericClass[] interfaces = GetInterfaces_internal ();
627 if (interfaces == null)
629 foreach (Type t in interfaces)
630 if (c.IsAssignableFrom (t))
635 Type parent = GetParentType ();
637 return c == typeof (object);
639 return c.IsAssignableFrom (parent);