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
61 Hashtable fields, ctors, methods;
64 internal MonoGenericClass ()
67 // this should not be used
68 throw new InvalidOperationException ();
71 [MethodImplAttribute(MethodImplOptions.InternalCall)]
72 protected extern void initialize (MethodInfo[] methods, ConstructorInfo[] ctors, FieldInfo[] fields, PropertyInfo[] properties, EventInfo[] events);
74 [MethodImplAttribute(MethodImplOptions.InternalCall)]
75 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
77 [MethodImplAttribute(MethodImplOptions.InternalCall)]
78 extern FieldInfo GetCorrespondingInflatedField (string generic);
80 [MethodImplAttribute(MethodImplOptions.InternalCall)]
81 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
83 [MethodImplAttribute(MethodImplOptions.InternalCall)]
84 protected extern MethodInfo[] GetMethods_internal (Type reflected_type);
86 [MethodImplAttribute(MethodImplOptions.InternalCall)]
87 protected extern ConstructorInfo[] GetConstructors_internal (Type reflected_type);
89 [MethodImplAttribute(MethodImplOptions.InternalCall)]
90 protected extern FieldInfo[] GetFields_internal (Type reflected_type);
92 [MethodImplAttribute(MethodImplOptions.InternalCall)]
93 protected extern PropertyInfo[] GetProperties_internal (Type reflected_type);
95 [MethodImplAttribute(MethodImplOptions.InternalCall)]
96 protected extern EventInfo[] GetEvents_internal (Type reflected_type);
98 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
99 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
106 MonoGenericClass parent = GetParentType () as MonoGenericClass;
108 parent.initialize ();
110 initialize (generic_type.GetMethods (flags),
111 generic_type.GetConstructors (flags),
112 generic_type.GetFields (flags),
113 generic_type.GetProperties (flags),
114 generic_type.GetEvents_internal (flags));
119 [MethodImplAttribute(MethodImplOptions.InternalCall)]
120 protected extern Type GetParentType ();
122 [MethodImplAttribute(MethodImplOptions.InternalCall)]
123 private extern Type InflateType_internal (Type type);
125 internal Type InflateType (Type type)
129 if (!type.IsGenericParameter && !type.ContainsGenericParameters)
131 return InflateType_internal (type);
134 [MethodImplAttribute(MethodImplOptions.InternalCall)]
135 protected extern MonoGenericClass[] GetInterfaces_internal ();
137 public override Type BaseType {
139 Type parent = GetParentType ();
140 return parent != null ? parent : generic_type.BaseType;
144 public override Type[] GetInterfaces ()
146 return GetInterfaces_internal ();
149 protected override bool IsValueTypeImpl ()
151 return generic_type.IsValueType;
154 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
159 if (fromNoninstanciated is MethodOnTypeBuilderInst) {
160 MethodOnTypeBuilderInst mbinst = (MethodOnTypeBuilderInst)fromNoninstanciated;
161 if (((ModuleBuilder)mbinst.mb.Module).assemblyb.IsCompilerContext)
162 fromNoninstanciated = mbinst.mb;
164 throw new ArgumentException ("method declaring type is not the generic type definition of type", "method");
167 if (fromNoninstanciated is MethodBuilder) {
168 MethodBuilder mb = (MethodBuilder)fromNoninstanciated;
170 // FIXME: We can't yet handle creating generic instantiations of
171 // MethodOnTypeBuilderInst objects
172 // Also, mono_image_get_method_on_inst_token () can't handle generic
174 if (!mb.IsGenericMethodDefinition) {
176 methods = new Hashtable ();
177 if (!methods.ContainsKey (mb))
178 methods [mb] = new MethodOnTypeBuilderInst (this, mb);
179 return (MethodInfo)methods [mb];
184 return GetCorrespondingInflatedMethod (fromNoninstanciated);
187 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
192 if (fromNoninstanciated is ConstructorBuilder) {
193 ConstructorBuilder cb = (ConstructorBuilder)fromNoninstanciated;
195 ctors = new Hashtable ();
196 if (!ctors.ContainsKey (cb))
197 ctors [cb] = new ConstructorOnTypeBuilderInst (this, cb);
198 return (ConstructorInfo)ctors [cb];
202 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
205 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
210 if (fromNoninstanciated is FieldBuilder) {
211 FieldBuilder fb = (FieldBuilder)fromNoninstanciated;
213 fields = new Hashtable ();
214 if (!fields.ContainsKey (fb))
215 fields [fb] = new FieldOnTypeBuilderInst (this, fb);
216 return (FieldInfo)fields [fb];
219 return GetCorrespondingInflatedField (fromNoninstanciated.Name);
222 public override MethodInfo[] GetMethods (BindingFlags bf)
224 ArrayList l = new ArrayList ();
227 // Walk up our class hierarchy and retrieve methods from our
231 Type current_type = this;
233 MonoGenericClass gi = current_type as MonoGenericClass;
235 l.AddRange (gi.GetMethods_impl (bf, this));
236 else if (current_type is TypeBuilder)
237 l.AddRange (current_type.GetMethods (bf));
239 // If we encounter a `MonoType', its
240 // GetMethodsByName() will return all the methods
241 // from its parent type(s), so we can stop here.
242 MonoType mt = (MonoType) current_type;
243 l.AddRange (mt.GetMethodsByName (null, bf, false, this));
247 if ((bf & BindingFlags.DeclaredOnly) != 0)
249 current_type = current_type.BaseType;
250 } while (current_type != null);
252 MethodInfo[] result = new MethodInfo [l.Count];
257 protected MethodInfo[] GetMethods_impl (BindingFlags bf, Type reftype)
259 ArrayList l = new ArrayList ();
261 MethodAttributes mattrs;
265 MethodInfo[] methods = GetMethods_internal (reftype);
267 for (int i = 0; i < methods.Length; i++) {
268 MethodInfo c = methods [i];
271 mattrs = c.Attributes;
272 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
273 if ((bf & BindingFlags.Public) != 0)
276 if ((bf & BindingFlags.NonPublic) != 0)
282 if ((mattrs & MethodAttributes.Static) != 0) {
283 if ((bf & BindingFlags.Static) != 0)
286 if ((bf & BindingFlags.Instance) != 0)
293 MethodInfo[] result = new MethodInfo [l.Count];
298 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
300 ArrayList l = new ArrayList ();
302 Type current_type = this;
304 MonoGenericClass gi = current_type as MonoGenericClass;
306 l.AddRange (gi.GetConstructors_impl (bf, this));
307 else if (current_type is TypeBuilder)
308 l.AddRange (current_type.GetConstructors (bf));
310 MonoType mt = (MonoType) current_type;
311 l.AddRange (mt.GetConstructors_internal (bf, this));
315 if ((bf & BindingFlags.DeclaredOnly) != 0)
317 current_type = current_type.BaseType;
318 } while (current_type != null);
320 ConstructorInfo[] result = new ConstructorInfo [l.Count];
325 protected ConstructorInfo[] GetConstructors_impl (BindingFlags bf, Type reftype)
327 ArrayList l = new ArrayList ();
329 MethodAttributes mattrs;
333 ConstructorInfo[] ctors = GetConstructors_internal (reftype);
335 for (int i = 0; i < ctors.Length; i++) {
336 ConstructorInfo c = ctors [i];
339 mattrs = c.Attributes;
340 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
341 if ((bf & BindingFlags.Public) != 0)
344 if ((bf & BindingFlags.NonPublic) != 0)
350 if ((mattrs & MethodAttributes.Static) != 0) {
351 if ((bf & BindingFlags.Static) != 0)
354 if ((bf & BindingFlags.Instance) != 0)
362 ConstructorInfo[] result = new ConstructorInfo [l.Count];
367 public override FieldInfo[] GetFields (BindingFlags bf)
369 ArrayList l = new ArrayList ();
371 Type current_type = this;
373 MonoGenericClass gi = current_type as MonoGenericClass;
375 l.AddRange (gi.GetFields_impl (bf, this));
376 else if (current_type is TypeBuilder)
377 l.AddRange (current_type.GetFields (bf));
379 MonoType mt = (MonoType) current_type;
380 l.AddRange (mt.GetFields_internal (bf, this));
384 if ((bf & BindingFlags.DeclaredOnly) != 0)
386 current_type = current_type.BaseType;
387 } while (current_type != null);
389 FieldInfo[] result = new FieldInfo [l.Count];
394 protected FieldInfo[] GetFields_impl (BindingFlags bf, Type reftype)
396 ArrayList l = new ArrayList ();
398 FieldAttributes fattrs;
402 FieldInfo[] fields = GetFields_internal (reftype);
404 for (int i = 0; i < fields.Length; i++) {
405 FieldInfo c = 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)
430 FieldInfo[] result = new FieldInfo [l.Count];
435 public override PropertyInfo[] GetProperties (BindingFlags bf)
437 ArrayList l = new ArrayList ();
439 Type current_type = this;
441 MonoGenericClass gi = current_type as MonoGenericClass;
443 l.AddRange (gi.GetProperties_impl (bf, this));
444 else if (current_type is TypeBuilder)
445 l.AddRange (current_type.GetProperties (bf));
447 MonoType mt = (MonoType) current_type;
448 l.AddRange (mt.GetPropertiesByName (null, bf, false, this));
452 if ((bf & BindingFlags.DeclaredOnly) != 0)
454 current_type = current_type.BaseType;
455 } while (current_type != null);
457 PropertyInfo[] result = new PropertyInfo [l.Count];
462 protected PropertyInfo[] GetProperties_impl (BindingFlags bf, Type reftype)
464 ArrayList l = new ArrayList ();
466 MethodAttributes mattrs;
471 PropertyInfo[] properties = GetProperties_internal (reftype);
473 for (int i = 0; i < properties.Length; i++) {
474 PropertyInfo c = properties [i];
477 accessor = c.GetGetMethod (true);
478 if (accessor == null)
479 accessor = c.GetSetMethod (true);
480 if (accessor == null)
482 mattrs = accessor.Attributes;
483 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
484 if ((bf & BindingFlags.Public) != 0)
487 if ((bf & BindingFlags.NonPublic) != 0)
493 if ((mattrs & MethodAttributes.Static) != 0) {
494 if ((bf & BindingFlags.Static) != 0)
497 if ((bf & BindingFlags.Instance) != 0)
504 PropertyInfo[] result = new PropertyInfo [l.Count];
509 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
510 Binder binder, Type returnType,
512 ParameterModifier[] modifiers)
514 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
515 PropertyInfo [] props = GetProperties (bindingAttr);
518 for (int i = 0; i < props.Length; ++i) {
519 if (String.Compare (props [i].Name, name, ignoreCase) == 0) {
521 al = new ArrayList ();
528 props = (PropertyInfo[])al.ToArray (typeof (PropertyInfo));
530 int count = props.Length;
532 if (count == 1 && (types == null || types.Length == 0) &&
533 (returnType == null || returnType == props[0].PropertyType))
537 binder = Binder.DefaultBinder;
539 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
542 public override EventInfo[] GetEvents (BindingFlags bf)
544 ArrayList l = new ArrayList ();
546 Type current_type = this;
548 MonoGenericClass gi = current_type as MonoGenericClass;
550 l.AddRange (gi.GetEvents_impl (bf, this));
551 else if (current_type is TypeBuilder)
552 l.AddRange (current_type.GetEvents (bf));
554 MonoType mt = (MonoType) current_type;
555 l.AddRange (mt.GetEvents (bf));
559 if ((bf & BindingFlags.DeclaredOnly) != 0)
561 current_type = current_type.BaseType;
562 } while (current_type != null);
564 EventInfo[] result = new EventInfo [l.Count];
569 protected EventInfo[] GetEvents_impl (BindingFlags bf, Type reftype)
571 ArrayList l = new ArrayList ();
573 MethodAttributes mattrs;
578 EventInfo[] events = GetEvents_internal (reftype);
580 for (int i = 0; i < events.Length; i++) {
581 EventInfo c = events [i];
584 accessor = c.GetAddMethod (true);
585 if (accessor == null)
586 accessor = c.GetRemoveMethod (true);
587 if (accessor == null)
589 mattrs = accessor.Attributes;
590 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
591 if ((bf & BindingFlags.Public) != 0)
594 if ((bf & BindingFlags.NonPublic) != 0)
600 if ((mattrs & MethodAttributes.Static) != 0) {
601 if ((bf & BindingFlags.Static) != 0)
604 if ((bf & BindingFlags.Instance) != 0)
611 EventInfo[] result = new EventInfo [l.Count];
616 public override Type[] GetNestedTypes (BindingFlags bf)
618 return generic_type.GetNestedTypes (bf);
621 public override bool IsAssignableFrom (Type c)
626 MonoGenericClass[] interfaces = GetInterfaces_internal ();
629 if (interfaces == null)
631 foreach (Type t in interfaces)
632 if (c.IsAssignableFrom (t))
637 Type parent = GetParentType ();
639 return c == typeof (object);
641 return c.IsAssignableFrom (parent);