svn path=/branches/mono-1-1-9/mcs/; revision=51206
[mono.git] / mcs / class / corlib / System.Reflection / MonoGenericClass.cs
1 //
2 // System.MonoType
3 //
4 // Sean MacIsaac (macisaac@ximian.com)
5 // Paolo Molaro (lupus@ximian.com)
6 // Patrik Torstensson (patrik.torstensson@labs2.com)
7 //
8 // (C) 2001 Ximian, Inc.
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
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:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
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.
32 //
33
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;
40
41 namespace System.Reflection
42 {
43         internal class MonoGenericClass : MonoType
44         {
45                 protected Type generic_type;
46                 bool initialized;
47
48                 [MonoTODO]
49                 internal MonoGenericClass ()
50                         : base (null)
51                 {
52                         // this should not be used
53                         throw new InvalidOperationException ();
54                 }
55
56                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
57                 protected extern void initialize (MethodInfo[] methods, ConstructorInfo[] ctors, FieldInfo[] fields, PropertyInfo[] properties, EventInfo[] events);
58
59                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
60                 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
61
62                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
63                 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
64
65                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
66                 extern FieldInfo GetCorrespondingInflatedField (string generic);
67
68                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
69                 protected extern MethodInfo[] GetMethods_internal (Type reflected_type);
70
71                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
72                 protected extern ConstructorInfo[] GetConstructors_internal (Type reflected_type);
73
74                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
75                 protected extern FieldInfo[] GetFields_internal (Type reflected_type);
76
77                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
78                 protected extern PropertyInfo[] GetProperties_internal (Type reflected_type);
79
80                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
81                 protected extern EventInfo[] GetEvents_internal (Type reflected_type);
82
83                 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
84                 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
85
86                 EventInfo[] get_event_info ()
87                 {
88                         if (generic_type is TypeBuilder)
89                                 return ((TypeBuilder) generic_type).GetEvents_internal (flags);
90                         else
91                                 return generic_type.GetEvents (flags);
92                 }
93
94                 void initialize ()
95                 {
96                         if (initialized)
97                                 return;
98
99                         MonoGenericClass parent = GetParentType ();
100                         if (parent != null)
101                                 parent.initialize ();
102
103                         initialize (generic_type.GetMethods (flags),
104                                     generic_type.GetConstructors (flags),
105                                     generic_type.GetFields (flags),
106                                     generic_type.GetProperties (flags),
107                                     get_event_info ());
108
109                         initialized = true;
110                 }
111
112                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
113                 protected extern MonoGenericClass GetParentType ();
114
115                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
116                 protected extern MonoGenericClass[] GetInterfaces_internal ();
117
118                 public override Type BaseType {
119                         get {
120                                 MonoGenericClass parent = GetParentType ();
121                                 return parent != null ? parent : generic_type.BaseType;
122                         }
123                 }
124
125                 public override Type[] GetInterfaces ()
126                 {
127                         return GetInterfaces_internal ();
128                 }
129
130                 protected override bool IsValueTypeImpl ()
131                 {
132                         return generic_type.IsValueType;
133                 }
134
135                 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
136                 {
137                         initialize ();
138
139                         return GetCorrespondingInflatedMethod (fromNoninstanciated);
140                 }
141
142                 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
143                 {
144                         initialize ();
145
146                         return GetCorrespondingInflatedConstructor (fromNoninstanciated);
147                 }
148
149                 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
150                 {
151                         initialize ();
152
153                         return GetCorrespondingInflatedField (fromNoninstanciated.Name);
154                 }
155                 
156                 public override MethodInfo[] GetMethods (BindingFlags bf)
157                 {
158                         ArrayList l = new ArrayList ();
159
160                         //
161                         // Walk up our class hierarchy and retrieve methods from our
162                         // parent classes.
163                         //
164
165                         Type current_type = this;
166                         do {
167                                 MonoGenericClass gi = current_type as MonoGenericClass;
168                                 if (gi != null)
169                                         l.AddRange (gi.GetMethods_impl (bf, this));
170                                 else if (current_type is TypeBuilder)
171                                         l.AddRange (current_type.GetMethods (bf));
172                                 else {
173                                         // If we encounter a `MonoType', its
174                                         // GetMethodsByName() will return all the methods
175                                         // from its parent type(s), so we can stop here.
176                                         MonoType mt = (MonoType) current_type;
177                                         l.AddRange (mt.GetMethodsByName (null, bf, false, this));
178                                         break;
179                                 }
180
181                                 if ((bf & BindingFlags.DeclaredOnly) != 0)
182                                         break;
183                                 current_type = current_type.BaseType;
184                         } while (current_type != null);
185
186                         MethodInfo[] result = new MethodInfo [l.Count];
187                         l.CopyTo (result);
188                         return result;
189                 }
190
191                 protected MethodInfo[] GetMethods_impl (BindingFlags bf, Type reftype)
192                 {
193                         ArrayList l = new ArrayList ();
194                         bool match;
195                         MethodAttributes mattrs;
196
197                         initialize ();
198
199                         MethodInfo[] methods = GetMethods_internal (reftype);
200
201                         for (int i = 0; i < methods.Length; i++) {
202                                 MethodInfo c = methods [i];
203
204                                 match = false;
205                                 mattrs = c.Attributes;
206                                 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
207                                         if ((bf & BindingFlags.Public) != 0)
208                                                 match = true;
209                                 } else {
210                                         if ((bf & BindingFlags.NonPublic) != 0)
211                                                 match = true;
212                                 }
213                                 if (!match)
214                                         continue;
215                                 match = false;
216                                 if ((mattrs & MethodAttributes.Static) != 0) {
217                                         if ((bf & BindingFlags.Static) != 0)
218                                                 match = true;
219                                 } else {
220                                         if ((bf & BindingFlags.Instance) != 0)
221                                                 match = true;
222                                 }
223                                 if (!match)
224                                         continue;
225                                 l.Add (c);
226                         }
227                         MethodInfo[] result = new MethodInfo [l.Count];
228                         l.CopyTo (result);
229                         return result;
230                 }
231
232                 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
233                 {
234                         ArrayList l = new ArrayList ();
235
236                         Type current_type = this;
237                         do {
238                                 MonoGenericClass gi = current_type as MonoGenericClass;
239                                 if (gi != null)
240                                         l.AddRange (gi.GetConstructors_impl (bf, this));
241                                 else if (current_type is TypeBuilder)
242                                         l.AddRange (current_type.GetConstructors (bf));
243                                 else {
244                                         MonoType mt = (MonoType) current_type;
245                                         l.AddRange (mt.GetConstructors_internal (bf, this));
246                                         break;
247                                 }
248
249                                 if ((bf & BindingFlags.DeclaredOnly) != 0)
250                                         break;
251                                 current_type = current_type.BaseType;
252                         } while (current_type != null);
253
254                         ConstructorInfo[] result = new ConstructorInfo [l.Count];
255                         l.CopyTo (result);
256                         return result;
257                 }
258
259                 protected ConstructorInfo[] GetConstructors_impl (BindingFlags bf, Type reftype)
260                 {
261                         ArrayList l = new ArrayList ();
262                         bool match;
263                         MethodAttributes mattrs;
264
265                         initialize ();
266
267                         ConstructorInfo[] ctors = GetConstructors_internal (reftype);
268
269                         for (int i = 0; i < ctors.Length; i++) {
270                                 ConstructorInfo c = ctors [i];
271
272                                 match = false;
273                                 mattrs = c.Attributes;
274                                 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
275                                         if ((bf & BindingFlags.Public) != 0)
276                                                 match = true;
277                                 } else {
278                                         if ((bf & BindingFlags.NonPublic) != 0)
279                                                 match = true;
280                                 }
281                                 if (!match)
282                                         continue;
283                                 match = false;
284                                 if ((mattrs & MethodAttributes.Static) != 0) {
285                                         if ((bf & BindingFlags.Static) != 0)
286                                                 match = true;
287                                 } else {
288                                         if ((bf & BindingFlags.Instance) != 0)
289                                                 match = true;
290                                 }
291                                 if (!match)
292                                         continue;
293                                 l.Add (c);
294                         }
295
296                         ConstructorInfo[] result = new ConstructorInfo [l.Count];
297                         l.CopyTo (result);
298                         return result;
299                 }
300
301                 public override FieldInfo[] GetFields (BindingFlags bf)
302                 {
303                         ArrayList l = new ArrayList ();
304
305                         Type current_type = this;
306                         do {
307                                 MonoGenericClass gi = current_type as MonoGenericClass;
308                                 if (gi != null)
309                                         l.AddRange (gi.GetFields_impl (bf, this));
310                                 else if (current_type is TypeBuilder)
311                                         l.AddRange (current_type.GetFields (bf));
312                                 else {
313                                         MonoType mt = (MonoType) current_type;
314                                         l.AddRange (mt.GetFields_internal (bf, this));
315                                         break;
316                                 }
317
318                                 if ((bf & BindingFlags.DeclaredOnly) != 0)
319                                         break;
320                                 current_type = current_type.BaseType;
321                         } while (current_type != null);
322
323                         FieldInfo[] result = new FieldInfo [l.Count];
324                         l.CopyTo (result);
325                         return result;
326                 }
327
328                 protected FieldInfo[] GetFields_impl (BindingFlags bf, Type reftype)
329                 {
330                         ArrayList l = new ArrayList ();
331                         bool match;
332                         FieldAttributes fattrs;
333
334                         initialize ();
335
336                         FieldInfo[] fields = GetFields_internal (reftype);
337
338                         for (int i = 0; i < fields.Length; i++) {
339                                 FieldInfo c = fields [i];
340
341                                 match = false;
342                                 fattrs = c.Attributes;
343                                 if ((fattrs & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) {
344                                         if ((bf & BindingFlags.Public) != 0)
345                                                 match = true;
346                                 } else {
347                                         if ((bf & BindingFlags.NonPublic) != 0)
348                                                 match = true;
349                                 }
350                                 if (!match)
351                                         continue;
352                                 match = false;
353                                 if ((fattrs & FieldAttributes.Static) != 0) {
354                                         if ((bf & BindingFlags.Static) != 0)
355                                                 match = true;
356                                 } else {
357                                         if ((bf & BindingFlags.Instance) != 0)
358                                                 match = true;
359                                 }
360                                 if (!match)
361                                         continue;
362                                 l.Add (c);
363                         }
364                         FieldInfo[] result = new FieldInfo [l.Count];
365                         l.CopyTo (result);
366                         return result;
367                 }
368
369                 public override PropertyInfo[] GetProperties (BindingFlags bf)
370                 {
371                         ArrayList l = new ArrayList ();
372
373                         Type current_type = this;
374                         do {
375                                 MonoGenericClass gi = current_type as MonoGenericClass;
376                                 if (gi != null)
377                                         l.AddRange (gi.GetProperties_impl (bf, this));
378                                 else if (current_type is TypeBuilder)
379                                         l.AddRange (current_type.GetProperties (bf));
380                                 else {
381                                         MonoType mt = (MonoType) current_type;
382                                         l.AddRange (mt.GetPropertiesByName (null, bf, false, this));
383                                         break;
384                                 }
385
386                                 if ((bf & BindingFlags.DeclaredOnly) != 0)
387                                         break;
388                                 current_type = current_type.BaseType;
389                         } while (current_type != null);
390
391                         PropertyInfo[] result = new PropertyInfo [l.Count];
392                         l.CopyTo (result);
393                         return result;
394                 }
395
396                 protected PropertyInfo[] GetProperties_impl (BindingFlags bf, Type reftype)
397                 {
398                         ArrayList l = new ArrayList ();
399                         bool match;
400                         MethodAttributes mattrs;
401                         MethodInfo accessor;
402
403                         initialize ();
404
405                         PropertyInfo[] properties = GetProperties_internal (reftype);
406
407                         for (int i = 0; i < properties.Length; i++) {
408                                 PropertyInfo c = properties [i];
409
410                                 match = false;
411                                 accessor = c.GetGetMethod (true);
412                                 if (accessor == null)
413                                         accessor = c.GetSetMethod (true);
414                                 if (accessor == null)
415                                         continue;
416                                 mattrs = accessor.Attributes;
417                                 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
418                                         if ((bf & BindingFlags.Public) != 0)
419                                                 match = true;
420                                 } else {
421                                         if ((bf & BindingFlags.NonPublic) != 0)
422                                                 match = true;
423                                 }
424                                 if (!match)
425                                         continue;
426                                 match = false;
427                                 if ((mattrs & MethodAttributes.Static) != 0) {
428                                         if ((bf & BindingFlags.Static) != 0)
429                                                 match = true;
430                                 } else {
431                                         if ((bf & BindingFlags.Instance) != 0)
432                                                 match = true;
433                                 }
434                                 if (!match)
435                                         continue;
436                                 l.Add (c);
437                         }
438                         PropertyInfo[] result = new PropertyInfo [l.Count];
439                         l.CopyTo (result);
440                         return result;
441                 }
442
443                 public override EventInfo[] GetEvents (BindingFlags bf)
444                 {
445                         ArrayList l = new ArrayList ();
446
447                         Type current_type = this;
448                         do {
449                                 MonoGenericClass gi = current_type as MonoGenericClass;
450                                 if (gi != null)
451                                         l.AddRange (gi.GetEvents_impl (bf, this));
452                                 else if (current_type is TypeBuilder)
453                                         l.AddRange (current_type.GetEvents (bf));
454                                 else {
455                                         MonoType mt = (MonoType) current_type;
456                                         l.AddRange (mt.GetEvents (bf));
457                                         break;
458                                 }
459
460                                 if ((bf & BindingFlags.DeclaredOnly) != 0)
461                                         break;
462                                 current_type = current_type.BaseType;
463                         } while (current_type != null);
464
465                         EventInfo[] result = new EventInfo [l.Count];
466                         l.CopyTo (result);
467                         return result;
468                 }
469
470                 protected EventInfo[] GetEvents_impl (BindingFlags bf, Type reftype)
471                 {
472                         ArrayList l = new ArrayList ();
473                         bool match;
474                         MethodAttributes mattrs;
475                         MethodInfo accessor;
476
477                         initialize ();
478
479                         EventInfo[] events = GetEvents_internal (reftype);
480
481                         for (int i = 0; i < events.Length; i++) {
482                                 EventInfo c = events [i];
483
484                                 match = false;
485                                 accessor = c.GetAddMethod (true);
486                                 if (accessor == null)
487                                         accessor = c.GetRemoveMethod (true);
488                                 if (accessor == null)
489                                         continue;
490                                 mattrs = accessor.Attributes;
491                                 if ((mattrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) {
492                                         if ((bf & BindingFlags.Public) != 0)
493                                                 match = true;
494                                 } else {
495                                         if ((bf & BindingFlags.NonPublic) != 0)
496                                                 match = true;
497                                 }
498                                 if (!match)
499                                         continue;
500                                 match = false;
501                                 if ((mattrs & MethodAttributes.Static) != 0) {
502                                         if ((bf & BindingFlags.Static) != 0)
503                                                 match = true;
504                                 } else {
505                                         if ((bf & BindingFlags.Instance) != 0)
506                                                 match = true;
507                                 }
508                                 if (!match)
509                                         continue;
510                                 l.Add (c);
511                         }
512                         EventInfo[] result = new EventInfo [l.Count];
513                         l.CopyTo (result);
514                         return result;
515                 }
516
517                 public override Type[] GetNestedTypes (BindingFlags bf)
518                 {
519                         return generic_type.GetNestedTypes (bf);
520                 }
521         }
522 }