Merge pull request #1322 from StephenMcConnel/bug23532
[mono.git] / mcs / class / corlib / System.Reflection / MonoGenericClass.cs
1 //
2 // System.Reflection.MonoGenericClass
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 #if !FULL_AOT_RUNTIME
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using System.Collections;
38 using System.Runtime.CompilerServices;
39 using System.Globalization;
40 using System.Runtime.Serialization;
41 using System.Text;
42 using System.Runtime.InteropServices;
43
44 namespace System.Reflection
45 {
46         /*
47          * MonoGenericClass represents an instantiation of a generic TypeBuilder. MS
48          * calls this class TypeBuilderInstantiation (a much better name). MS returns 
49          * NotImplementedException for many of the methods but we can't do that as gmcs
50          * depends on them.
51          */
52         [StructLayout (LayoutKind.Sequential)]
53         sealed class MonoGenericClass :
54 #if NET_4_5
55                 TypeInfo
56 #else
57                 Type
58 #endif  
59         {
60                 #region Keep in sync with object-internals.h
61 #pragma warning disable 649
62                 internal Type generic_type;
63                 Type[] type_arguments;
64                 bool initialized;
65 #pragma warning restore 649
66                 #endregion
67
68                 Hashtable fields, ctors, methods;
69
70                 internal MonoGenericClass ()
71                 {
72                         // this should not be used
73                         throw new InvalidOperationException ();
74                 }
75
76                 internal MonoGenericClass (Type tb, Type[] args)
77                 {
78                         this.generic_type = tb;
79                         this.type_arguments = args;
80                         /*
81                         This is a temporary hack until we can fix the rest of the runtime
82                         to properly handle this class to be a complete UT.
83
84                         We must not regisrer this with the runtime after the type is created
85                         otherwise created_type.MakeGenericType will return an instance of MonoGenericClass,
86                         which is very very broken.
87                         */
88                         if (tb is TypeBuilder && !(tb as TypeBuilder).is_created)
89                                 register_with_runtime (this);
90                         
91                 }
92
93                 internal override Type InternalResolve ()
94                 {
95                         Type gtd = generic_type.InternalResolve ();
96                         Type[] args = new Type [type_arguments.Length];
97                         for (int i = 0; i < type_arguments.Length; ++i)
98                                 args [i] = type_arguments [i].InternalResolve ();
99                         return gtd.MakeGenericType (args);
100                 }
101
102                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
103                 extern void initialize (FieldInfo[] fields);
104
105                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
106                 internal static extern void register_with_runtime (Type type);
107
108                 internal bool IsCreated {
109                         get {
110                                 TypeBuilder tb = generic_type as TypeBuilder;
111                                 return tb != null ? tb.is_created : true;
112                         }
113                 }
114
115                 private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
116                 BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
117
118                 void initialize ()
119                 {
120                         if (initialized)
121                                 return;
122
123                         MonoGenericClass parent = GetParentType () as MonoGenericClass;
124                         if (parent != null)
125                                 parent.initialize ();
126                                 
127                         initialize (generic_type.GetFields (flags));
128
129                         initialized = true;
130                 }
131
132                 Type GetParentType ()
133                 {
134                         return InflateType (generic_type.BaseType);             
135                 }
136
137                 internal Type InflateType (Type type)
138                 {
139                         return InflateType (type, type_arguments, null);
140                 }
141
142                 internal Type InflateType (Type type, Type[] method_args)
143                 {
144                         return InflateType (type, type_arguments, method_args);
145                 }
146
147                 internal static Type InflateType (Type type, Type[] type_args, Type[] method_args)
148                 {
149                         if (type == null)
150                                 return null;
151                         if (!type.IsGenericParameter && !type.ContainsGenericParameters)
152                                 return type;
153                         if (type.IsGenericParameter) {
154                                 if (type.DeclaringMethod == null)
155                                         return type_args == null ? type : type_args [type.GenericParameterPosition];
156                                 return method_args == null ? type : method_args [type.GenericParameterPosition];
157                         }
158                         if (type.IsPointer)
159                                 return InflateType (type.GetElementType (), type_args, method_args).MakePointerType ();
160                         if (type.IsByRef)
161                                 return InflateType (type.GetElementType (), type_args, method_args).MakeByRefType ();
162                         if (type.IsArray) {
163                                 if (type.GetArrayRank () > 1)
164                                         return InflateType (type.GetElementType (), type_args, method_args).MakeArrayType (type.GetArrayRank ());
165                                 
166                                 if (type.ToString ().EndsWith ("[*]", StringComparison.Ordinal)) /*FIXME, the reflection API doesn't offer a way around this*/
167                                         return InflateType (type.GetElementType (), type_args, method_args).MakeArrayType (1);
168                                 return InflateType (type.GetElementType (), type_args, method_args).MakeArrayType ();
169                         }
170
171                         Type[] args = type.GetGenericArguments ();
172                         for (int i = 0; i < args.Length; ++i)
173                                 args [i] = InflateType (args [i], type_args, method_args);
174
175                         Type gtd = type.IsGenericTypeDefinition ? type : type.GetGenericTypeDefinition ();
176                         return gtd.MakeGenericType (args);
177                 }
178                 
179                 public override Type BaseType {
180                         get { return generic_type.BaseType; }
181                 }
182
183                 public override Type[] GetInterfaces ()
184                 {
185                         throw new NotSupportedException ();
186                 }
187
188                 protected override bool IsValueTypeImpl ()
189                 {
190                         return generic_type.IsValueType;
191                 }
192
193                 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
194                 {
195                         initialize ();
196
197                         if (methods == null)
198                                 methods = new Hashtable ();
199                         if (!methods.ContainsKey (fromNoninstanciated))
200                                 methods [fromNoninstanciated] = new MethodOnTypeBuilderInst (this, fromNoninstanciated);
201                         return (MethodInfo)methods [fromNoninstanciated];
202                 }
203
204                 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
205                 {
206                         initialize ();
207
208                         if (ctors == null)
209                                 ctors = new Hashtable ();
210                         if (!ctors.ContainsKey (fromNoninstanciated))
211                                 ctors [fromNoninstanciated] = new ConstructorOnTypeBuilderInst (this, fromNoninstanciated);
212                         return (ConstructorInfo)ctors [fromNoninstanciated];
213                 }
214
215                 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
216                 {
217                         initialize ();
218                         if (fields == null)
219                                 fields = new Hashtable ();
220                         if (!fields.ContainsKey (fromNoninstanciated))
221                                 fields [fromNoninstanciated] = new FieldOnTypeBuilderInst (this, fromNoninstanciated);
222                         return (FieldInfo)fields [fromNoninstanciated];
223                 }
224                 
225                 public override MethodInfo[] GetMethods (BindingFlags bf)
226                 {
227                         throw new NotSupportedException ();
228                 }
229
230                 public override ConstructorInfo[] GetConstructors (BindingFlags bf)
231                 {
232                         throw new NotSupportedException ();
233                 }
234
235                 public override FieldInfo[] GetFields (BindingFlags bf)
236                 {
237                         throw new NotSupportedException ();
238                 }
239
240                 public override PropertyInfo[] GetProperties (BindingFlags bf)
241                 {
242                         throw new NotSupportedException ();
243                 }
244
245                 public override EventInfo[] GetEvents (BindingFlags bf)
246                 {
247                         throw new NotSupportedException ();
248                 }
249
250                 public override Type[] GetNestedTypes (BindingFlags bf)
251                 {
252                         throw new NotSupportedException ();
253                 }
254
255                 public override bool IsAssignableFrom (Type c)
256                 {
257                         throw new NotSupportedException ();
258                 }
259
260                 public override Type UnderlyingSystemType {
261                         get { return this; }
262                 }
263
264                 public override Assembly Assembly {
265                         get { return generic_type.Assembly; }
266                 }
267
268                 public override Module Module {
269                         get { return generic_type.Module; }
270                 }
271
272                 public override string Name {
273                         get { return generic_type.Name; }
274                 }
275
276                 public override string Namespace {
277                         get { return generic_type.Namespace; }
278                 }
279
280                 public override string FullName {
281                         get { return format_name (true, false); }
282                 }
283
284                 public override string AssemblyQualifiedName {
285                         get { return format_name (true, true); }
286                 }
287
288                 public override Guid GUID {
289                         get { throw new NotSupportedException (); }
290                 }
291
292                 string format_name (bool full_name, bool assembly_qualified)
293                 {
294                         StringBuilder sb = new StringBuilder (generic_type.FullName);
295
296                         sb.Append ("[");
297                         for (int i = 0; i < type_arguments.Length; ++i) {
298                                 if (i > 0)
299                                         sb.Append (",");
300                                 
301                                 string name;
302                                 if (full_name) {
303                                         string assemblyName = type_arguments [i].Assembly.FullName;
304                                         name = type_arguments [i].FullName;
305                                         if (name != null && assemblyName != null)
306                                                 name = name + ", " + assemblyName;
307                                 } else {
308                                         name = type_arguments [i].ToString ();
309                                 }
310                                 if (name == null) {
311                                         return null;
312                                 }
313                                 if (full_name)
314                                         sb.Append ("[");
315                                 sb.Append (name);
316                                 if (full_name)
317                                         sb.Append ("]");
318                         }
319                         sb.Append ("]");
320                         if (assembly_qualified) {
321                                 sb.Append (", ");
322                                 sb.Append (generic_type.Assembly.FullName);
323                         }
324                         return sb.ToString ();
325                 }
326
327                 public override string ToString ()
328                 {
329                         return format_name (false, false);
330                 }
331
332                 public override Type GetGenericTypeDefinition ()
333                 {
334                         return generic_type;
335                 }
336
337                 public override Type[] GetGenericArguments ()
338                 {
339                         Type[] ret = new Type [type_arguments.Length];
340                         type_arguments.CopyTo (ret, 0);
341                         return ret;
342                 }
343
344                 public override bool ContainsGenericParameters {
345                         get {
346                                 foreach (Type t in type_arguments) {
347                                         if (t.ContainsGenericParameters)
348                                                 return true;
349                                 }
350                                 return false;
351                         }
352                 }
353
354                 public override bool IsGenericTypeDefinition {
355                         get { return false; }
356                 }
357
358                 public override bool IsGenericType {
359                         get { return true; }
360                 }
361
362                 public override Type DeclaringType {
363                         get { return generic_type.DeclaringType; }
364                 }
365
366                 public override RuntimeTypeHandle TypeHandle {
367                         get {
368                                 throw new NotSupportedException ();
369                         }
370                 }
371
372                 public override Type MakeArrayType ()
373                 {
374                         return new ArrayType (this, 0);
375                 }
376
377                 public override Type MakeArrayType (int rank)
378                 {
379                         if (rank < 1)
380                                 throw new IndexOutOfRangeException ();
381                         return new ArrayType (this, rank);
382                 }
383
384                 public override Type MakeByRefType ()
385                 {
386                         return new ByRefType (this);
387                 }
388
389                 public override Type MakePointerType ()
390                 {
391                         return new PointerType (this);
392                 }
393
394                 public override Type GetElementType ()
395                 {
396                         throw new NotSupportedException ();
397                 }
398
399                 protected override bool HasElementTypeImpl ()
400                 {
401                         return false;
402                 }
403
404                 protected override bool IsCOMObjectImpl ()
405                 {
406                         return false;
407                 }
408
409                 protected override bool IsPrimitiveImpl ()
410                 {
411                         return false;
412                 }
413
414                 protected override bool IsArrayImpl ()
415                 {
416                         return false;
417                 }
418
419                 protected override bool IsByRefImpl ()
420                 {
421                         return false;
422                 }
423
424                 protected override bool IsPointerImpl ()
425                 {
426                         return false;
427                 }
428
429                 protected override TypeAttributes GetAttributeFlagsImpl ()
430                 {
431                         return generic_type.Attributes; 
432                 }
433
434                 //stuff that throws
435                 public override Type GetInterface (string name, bool ignoreCase)
436                 {
437                         throw new NotSupportedException ();
438                 }
439
440                 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
441                 {
442                         throw new NotSupportedException ();
443                 }
444
445                 public override FieldInfo GetField( string name, BindingFlags bindingAttr)
446                 {
447                         throw new NotSupportedException ();
448                 }
449
450                 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
451                 {
452                         throw new NotSupportedException ();
453                 }
454
455                 public override Type GetNestedType (string name, BindingFlags bindingAttr)
456                 {
457                         throw new NotSupportedException ();
458                 }
459
460                 public override object InvokeMember (string name, BindingFlags invokeAttr,
461                                                      Binder binder, object target, object[] args,
462                                                      ParameterModifier[] modifiers,
463                                                      CultureInfo culture, string[] namedParameters)
464                 {
465                         throw new NotSupportedException ();
466                 }
467
468                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder,
469                                                              CallingConventions callConvention, Type[] types,
470                                                              ParameterModifier[] modifiers)
471                 {
472                         throw new NotSupportedException ();
473                 }
474
475                 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder,
476                                                                  Type returnType, Type[] types, ParameterModifier[] modifiers)
477                 {
478                         throw new NotSupportedException ();
479                 }
480
481                 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
482                                                                        Binder binder,
483                                                                        CallingConventions callConvention,
484                                                                        Type[] types,
485                                                                        ParameterModifier[] modifiers)
486                 {
487                         throw new NotSupportedException ();
488                 }
489
490                 //MemberInfo
491                 public override bool IsDefined (Type attributeType, bool inherit)
492                 {
493                         throw new NotSupportedException ();
494                 }
495
496                 public override object [] GetCustomAttributes (bool inherit)
497                 {
498                         if (IsCreated)
499                                 return generic_type.GetCustomAttributes (inherit);
500                         throw new NotSupportedException ();
501                 }
502
503                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
504                 {
505                         if (IsCreated)
506                                 return generic_type.GetCustomAttributes (attributeType, inherit);
507                         throw new NotSupportedException ();
508                 }
509
510                 internal override bool IsUserType {
511                         get {
512                                 foreach (var t in type_arguments) {
513                                         if (t.IsUserType)
514                                                 return true;
515                                 }
516                                 return false;
517                         }
518                 }
519
520         }
521 }
522
523 #endif