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