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