e0f48d36255c5437b7707e20716623c247846731
[mono.git] / mcs / class / corlib / ReferenceSources / RuntimeType.cs
1 //
2 // RuntimeType.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2015 Xamarin Inc (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Reflection;
30 using System.Runtime.CompilerServices;
31 using System.Threading;
32 using System.Collections.Generic;
33 using System.Runtime.InteropServices;
34 using System.Globalization;
35 #if MONO_COM
36 using System.Reflection.Emit;
37 #endif
38 using System.Diagnostics.Contracts;
39 using System.Security;
40
41 namespace System
42 {
43         partial class RuntimeType
44         {
45                 internal virtual MonoCMethod GetDefaultConstructor ()
46                 {
47                         // TODO: Requires MonoType
48                         throw new NotSupportedException ();
49                 }
50
51                 string GetDefaultMemberName ()
52                 {
53                         object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
54                         return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
55                 }
56
57                 internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
58                 {
59                         bool bNeedSecurityCheck = true;
60                         bool bCanBeCached = false;
61                         bool bSecurityCheckOff = false;
62
63                         if (!skipCheckThis)
64                                 CreateInstanceCheckThis();
65
66                         if (!fillCache)
67                                 bSecurityCheckOff = true;
68
69                         return CreateInstanceMono (!publicOnly);
70                 }
71
72                 object CreateInstanceMono (bool nonPublic)
73                 {
74                         var ctor = GetDefaultConstructor ();
75                         if (!nonPublic && ctor != null && !ctor.IsPublic) {
76                                 ctor = null;
77                         }
78
79                         if (ctor == null) {
80                                 Type elementType = this.GetRootElementType();
81                                 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
82                                         throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
83
84                                 if (IsValueType)
85                                         return CreateInstanceInternal (this);
86
87                                 throw new MissingMethodException (Locale.GetText ("Default constructor not found for type " + FullName));
88                         }
89
90                         // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
91                         if (IsAbstract) {
92                                 throw new MissingMethodException (Locale.GetText ("Cannot create an abstract class '{0}'.", FullName));
93                         }
94
95                         return ctor.InternalInvoke (null, null);
96                 }
97
98                 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
99                 {
100                         bool failed = false;
101                         var res = TryConvertToType (value, ref failed);
102                         if (!failed)
103                                 return res;
104
105                         if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
106                                 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
107
108                         if (binder != null && binder != Type.DefaultBinder)
109                                 return binder.ChangeType (value, this, culture);
110
111                         throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
112                 }
113
114                 object TryConvertToType (object value, ref bool failed)
115                 {
116                         if (IsInstanceOfType (value)) {
117                                 return value;
118                         }
119
120                         if (IsByRef) {
121                                 var elementType = GetElementType ();
122                                 if (value == null || elementType.IsInstanceOfType (value)) {
123                                         return value;
124                                 }
125                         }
126
127                         if (value == null)
128                                 return value;
129
130                         if (IsEnum) {
131                                 var type = Enum.GetUnderlyingType (this);
132                                 if (type == value.GetType ())
133                                         return value;
134                                 var res = IsConvertibleToPrimitiveType (value, this);
135                                 if (res != null)
136                                         return res;
137                         } else if (IsPrimitive) {
138                                 var res = IsConvertibleToPrimitiveType (value, this);
139                                 if (res != null)
140                                         return res;
141                         } else if (IsPointer) {
142                                 var vtype = value.GetType ();
143                                 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
144                                         return value;
145                         }
146
147                         failed = true;
148                         return null;
149                 }
150
151                 // Binder uses some incompatible conversion rules. For example
152                 // int value cannot be used with decimal parameter but in other
153                 // ways it's more flexible than normal convertor, for example
154                 // long value can be used with int based enum
155                 static object IsConvertibleToPrimitiveType (object value, Type targetType)
156                 {
157                         var type = value.GetType ();
158                         if (type.IsEnum) {
159                                 type = Enum.GetUnderlyingType (type);
160                                 if (type == targetType)
161                                         return value;
162                         }
163
164                         var from = Type.GetTypeCode (type);
165                         var to = Type.GetTypeCode (targetType);
166
167                         switch (to) {
168                                 case TypeCode.Char:
169                                         switch (from) {
170                                                 case TypeCode.Byte:
171                                                         return (Char) (Byte) value;
172                                                 case TypeCode.UInt16:
173                                                         return value;
174                                         }
175                                         break;
176                                 case TypeCode.Int16:
177                                         switch (from) {
178                                                 case TypeCode.Byte:
179                                                         return (Int16) (Byte) value;
180                                                 case TypeCode.SByte:
181                                                         return (Int16) (SByte) value;
182                                         }
183                                         break;
184                                 case TypeCode.UInt16:
185                                         switch (from) {
186                                                 case TypeCode.Byte:
187                                                         return (UInt16) (Byte) value;
188                                                 case TypeCode.Char:
189                                                         return value;
190                                         }
191                                         break;
192                                 case TypeCode.Int32:
193                                         switch (from) {
194                                                 case TypeCode.Byte:
195                                                         return (Int32) (Byte) value;
196                                                 case TypeCode.SByte:
197                                                         return (Int32) (SByte) value;
198                                                 case TypeCode.Char:
199                                                         return (Int32) (Char) value;
200                                                 case TypeCode.Int16:
201                                                         return (Int32) (Int16) value;
202                                                 case TypeCode.UInt16:
203                                                         return (Int32) (UInt16) value;
204                                         }
205                                         break;
206                                 case TypeCode.UInt32:
207                                         switch (from) {
208                                                 case TypeCode.Byte:
209                                                         return (UInt32) (Byte) value;
210                                                 case TypeCode.Char:
211                                                         return (UInt32) (Char) value;
212                                                 case TypeCode.UInt16:
213                                                         return (UInt32) (UInt16) value;
214                                         }
215                                         break;
216                                 case TypeCode.Int64:
217                                         switch (from) {
218                                                 case TypeCode.Byte:
219                                                         return (Int64) (Byte) value;
220                                                 case TypeCode.SByte:
221                                                         return (Int64) (SByte) value;
222                                                 case TypeCode.Int16:
223                                                         return (Int64) (Int16) value;
224                                                 case TypeCode.Char:
225                                                         return (Int64) (Char) value;
226                                                 case TypeCode.UInt16:
227                                                         return (Int64) (UInt16) value;
228                                                 case TypeCode.Int32:
229                                                         return (Int64) (Int32) value;
230                                                 case TypeCode.UInt32:
231                                                         return (Int64) (UInt32) value;
232                                         }
233                                         break;
234                                 case TypeCode.UInt64:
235                                         switch (from) {
236                                                 case TypeCode.Byte:
237                                                         return (UInt64) (Byte) value;
238                                                 case TypeCode.Char:
239                                                         return (UInt64) (Char) value;
240                                                 case TypeCode.UInt16:
241                                                         return (UInt64) (UInt16) value;
242                                                 case TypeCode.UInt32:
243                                                         return (UInt64) (UInt32) value;
244                                         }
245                                         break;
246                                 case TypeCode.Single:
247                                         switch (from) {
248                                                 case TypeCode.Byte:
249                                                         return (Single) (Byte) value;
250                                                 case TypeCode.SByte:
251                                                         return (Single) (SByte) value;
252                                                 case TypeCode.Int16:
253                                                         return (Single) (Int16) value;
254                                                 case TypeCode.Char:
255                                                         return (Single) (Char) value;
256                                                 case TypeCode.UInt16:
257                                                         return (Single) (UInt16) value;
258                                                 case TypeCode.Int32:
259                                                         return (Single) (Int32) value;
260                                                 case TypeCode.UInt32:
261                                                         return (Single) (UInt32) value;
262                                                 case TypeCode.Int64:
263                                                         return (Single) (Int64) value;
264                                                 case TypeCode.UInt64:
265                                                         return (Single) (UInt64) value;
266                                         }
267                                         break;
268                                 case TypeCode.Double:
269                                         switch (from) {
270                                                 case TypeCode.Byte:
271                                                         return (Double) (Byte) value;
272                                                 case TypeCode.SByte:
273                                                         return (Double) (SByte) value;
274                                                 case TypeCode.Char:
275                                                         return (Double) (Char) value;
276                                                 case TypeCode.Int16:
277                                                         return (Double) (Int16) value;
278                                                 case TypeCode.UInt16:
279                                                         return (Double) (UInt16) value;
280                                                 case TypeCode.Int32:
281                                                         return (Double) (Int32) value;
282                                                 case TypeCode.UInt32:
283                                                         return (Double) (UInt32) value;
284                                                 case TypeCode.Int64:
285                                                         return (Double) (Int64) value;
286                                                 case TypeCode.UInt64:
287                                                         return (Double) (UInt64) value;
288                                                 case TypeCode.Single:
289                                                         return (Double) (Single) value;
290                                         }
291                                         break;
292                         }
293
294                         // Everything else is rejected
295                         return null;
296                 }
297
298                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
299                 extern Type make_array_type (int rank);
300
301                 public override Type MakeArrayType ()
302                 {
303                         return make_array_type (0);
304                 }
305
306                 public override Type MakeArrayType (int rank)
307                 {
308                         if (rank < 1 || rank > 255)
309                                 throw new IndexOutOfRangeException ();
310                         return make_array_type (rank);
311                 }
312
313                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
314                 extern Type make_byref_type ();
315
316                 public override Type MakeByRefType ()
317                 {
318                         if (IsByRef)
319                                 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
320                         return make_byref_type ();
321                 }
322
323                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
324                 static extern Type MakePointerType (Type type);
325
326                 public override Type MakePointerType ()
327                 {
328                         return MakePointerType (this);
329                 }
330
331                 public override StructLayoutAttribute StructLayoutAttribute {
332                         get {
333                                 return GetStructLayoutAttribute ();
334                         }
335                 }
336
337                 public override bool ContainsGenericParameters {
338                         get {
339                                 if (IsGenericParameter)
340                                         return true;
341
342                                 if (IsGenericType) {
343                                         foreach (Type arg in GetGenericArguments ())
344                                                 if (arg.ContainsGenericParameters)
345                                                         return true;
346                                 }
347
348                                 if (HasElementType)
349                                         return GetElementType ().ContainsGenericParameters;
350
351                                 return false;
352                         }
353                 }
354
355                 public override Type[] GetGenericParameterConstraints()
356                 {
357                         if (!IsGenericParameter)
358                                 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
359                         Contract.EndContractBlock();
360
361                         Type[] constraints = GetGenericParameterConstraints_impl ();
362
363                         if (constraints == null)
364                                 constraints = EmptyArray<Type>.Value;
365
366                         return constraints;
367                 }
368
369                 public override Type MakeGenericType (params Type[] typeArguments)
370                 {
371                         if (IsUserType)
372                                 throw new NotSupportedException ();
373                         if (!IsGenericTypeDefinition)
374                                 throw new InvalidOperationException ("not a generic type definition");
375                         if (typeArguments == null)
376                                 throw new ArgumentNullException ("typeArguments");
377                         if (GetGenericArguments().Length != typeArguments.Length)
378                                 throw new ArgumentException (String.Format ("The type or method has {0} generic parameter(s) but {1} generic argument(s) where provided. A generic argument must be provided for each generic parameter.", GetGenericArguments ().Length, typeArguments.Length), "typeArguments");
379
380                         bool hasUserType = false;
381
382                         Type[] systemTypes = new Type[typeArguments.Length];
383                         for (int i = 0; i < typeArguments.Length; ++i) {
384                                 Type t = typeArguments [i];
385                                 if (t == null)
386                                         throw new ArgumentNullException ("typeArguments");
387
388                                 if (!(t is MonoType))
389                                         hasUserType = true;
390                                 systemTypes [i] = t;
391                         }
392
393                         if (hasUserType) {
394 #if FULL_AOT_RUNTIME
395                                 throw new NotSupportedException ("User types are not supported under full aot");
396 #else
397                                 return new MonoGenericClass (this, typeArguments);
398 #endif
399                         }
400
401                         Type res = MakeGenericType (this, systemTypes);
402                         if (res == null)
403                                 throw new TypeLoadException ();
404                         return res;
405                 }
406
407                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408                 static extern Type MakeGenericType (Type gt, Type [] types);
409
410                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
411                 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
412
413                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
414                 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);              
415
416                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
417                 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
418
419                 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
420                 {
421                         if (IsGenericParameter)
422                                 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
423                 
424                         if ((object)ifaceType == null)
425                                 throw new ArgumentNullException("ifaceType");
426                         Contract.EndContractBlock();
427
428                         RuntimeType ifaceRtType = ifaceType as RuntimeType;
429
430                         if (ifaceRtType == null)
431                                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
432
433                         InterfaceMapping res;
434                         if (!ifaceType.IsInterface)
435                                 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
436                         if (IsInterface)
437                                 throw new ArgumentException ("'this' type cannot be an interface itself");
438                         res.TargetType = this;
439                         res.InterfaceType = ifaceType;
440                         GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
441                         if (res.TargetMethods == null)
442                                 throw new ArgumentException (Locale.GetText ("Interface not found"), "ifaceType");
443
444                         return res;
445                 }
446
447                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
448                 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);                
449
450                 public override Guid GUID {
451                         get {
452                                 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
453                                 if (att.Length == 0)
454                                         return Guid.Empty;
455                                 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
456                         }
457                 }
458
459                 StructLayoutAttribute GetStructLayoutAttribute ()
460                 {
461                         LayoutKind kind;
462
463                         if (IsLayoutSequential)
464                                 kind = LayoutKind.Sequential;
465                         else if (IsExplicitLayout)
466                                 kind = LayoutKind.Explicit;
467                         else
468                                 kind = LayoutKind.Auto;
469
470                         StructLayoutAttribute attr = new StructLayoutAttribute (kind);
471
472                         if (IsUnicodeClass)
473                                 attr.CharSet = CharSet.Unicode;
474                         else if (IsAnsiClass)
475                                 attr.CharSet = CharSet.Ansi;
476                         else
477                                 attr.CharSet = CharSet.Auto;
478
479                         if (kind != LayoutKind.Auto) {
480                                 int packing;
481                                 GetPacking (out packing, out attr.Size);
482                                 // 0 means no data provided, we end up with default value
483                                 if (packing != 0)
484                                         attr.Pack = packing;
485                         }
486
487                         return attr;
488                 }
489
490                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
491                 extern void GetPacking (out int packing, out int size);
492
493 #if MONO_COM
494                 private static Dictionary<Guid, Type> clsid_types;
495                 private static AssemblyBuilder clsid_assemblybuilder;
496 #endif
497
498                 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
499                 {
500 #if MONO_COM
501                         Type result;
502
503                         if (clsid_types == null)
504                         {
505                                 Dictionary<Guid, Type> new_clsid_types = new Dictionary<Guid, Type> ();
506                                 Interlocked.CompareExchange<Dictionary<Guid, Type>>(
507                                         ref clsid_types, new_clsid_types, null);
508                         }
509
510                         lock (clsid_types) {
511                                 if (clsid_types.TryGetValue(clsid, out result))
512                                         return result;
513
514                                 if (clsid_assemblybuilder == null)
515                                 {
516                                         AssemblyName assemblyname = new AssemblyName ();
517                                         assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
518                                         clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
519                                                 assemblyname, AssemblyBuilderAccess.Run);
520                                 }
521                                 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
522                                         clsid.ToString ());
523
524                                 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
525                                         TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
526
527                                 Type[] guidattrtypes = new Type[] { typeof(string) };
528
529                                 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
530                                         typeof(GuidAttribute).GetConstructor (guidattrtypes),
531                                         new object[] { clsid.ToString () });
532
533                                 typebuilder.SetCustomAttribute (customattr);
534
535                                 customattr = new CustomAttributeBuilder (
536                                         typeof(ComImportAttribute).GetConstructor (EmptyTypes),
537                                         new object[0] {});
538
539                                 typebuilder.SetCustomAttribute (customattr);
540
541                                 result = typebuilder.CreateType ();
542
543                                 clsid_types.Add(clsid, result);
544
545                                 return result;
546                         }
547 #else
548                         throw new NotImplementedException ("Unmanaged activation removed");
549 #endif
550                 }
551
552                 protected override TypeCode GetTypeCodeImpl ()
553                 {
554                         return GetTypeCodeImplInternal (this);
555                 }
556
557                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
558                 extern static TypeCode GetTypeCodeImplInternal (Type type);             
559
560                 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
561                 {
562                         throw new NotImplementedException ("Unmanaged activation is not supported");
563                 }
564
565                 public override string ToString()
566                 {
567                         return getFullName (false, false);
568                 }
569
570                 bool IsGenericCOMObjectImpl ()
571                 {
572                         return false;
573                 }
574
575                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
576                 static extern object CreateInstanceInternal (Type type);
577
578                 public extern override MethodBase DeclaringMethod {
579                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
580                         get;
581                 }               
582                 
583                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
584                 internal extern string getFullName(bool full_name, bool assembly_qualified);
585
586                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587                 public extern override Type [] GetGenericArguments ();
588
589                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
590                 extern GenericParameterAttributes GetGenericParameterAttributes ();
591
592                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
593                 extern Type[] GetGenericParameterConstraints_impl ();
594
595                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
596                 extern int GetGenericParameterPosition ();
597
598                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
599                 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
600
601                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
602                 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
603
604                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
605                 public extern override Type[] GetInterfaces();
606
607                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
608                 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);           
609
610                 public override string AssemblyQualifiedName {
611                         get {
612                                 return getFullName (true, true);
613                         }
614                 }
615
616                 public extern override Type DeclaringType {
617                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
618                         get;
619                 }
620
621                 public override string FullName {
622                         get {
623                                 throw new NotImplementedException ();
624                         }
625                 }
626
627                 public extern override string Name {
628                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
629                         get;
630                 }
631
632                 public extern override string Namespace {
633                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
634                         get;
635                 }
636
637                 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
638                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
639                 public extern int get_core_clr_security_level ();
640
641                 public override bool IsSecurityTransparent {
642                         get { return get_core_clr_security_level () == 0; }
643                 }
644
645                 public override bool IsSecurityCritical {
646                         get { return get_core_clr_security_level () > 0; }
647                 }
648
649                 public override bool IsSecuritySafeCritical {
650                         get { return get_core_clr_security_level () == 1; }
651                 }               
652         }
653 }