5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (C) 2015 Xamarin Inc (http://www.xamarin.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
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;
36 using System.Reflection.Emit;
38 using System.Diagnostics.Contracts;
39 using System.Security;
43 partial class RuntimeType
45 internal virtual MonoCMethod GetDefaultConstructor ()
47 // TODO: Requires MonoType
48 throw new NotSupportedException ();
51 string GetDefaultMemberName ()
53 object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
54 return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
57 internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
59 bool bNeedSecurityCheck = true;
60 bool bCanBeCached = false;
61 bool bSecurityCheckOff = false;
64 CreateInstanceCheckThis();
67 bSecurityCheckOff = true;
69 return CreateInstanceMono (!publicOnly);
72 object CreateInstanceMono (bool nonPublic)
74 var ctor = GetDefaultConstructor ();
75 if (!nonPublic && ctor != null && !ctor.IsPublic) {
80 Type elementType = this.GetRootElementType();
81 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
82 throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
85 return CreateInstanceInternal (this);
87 throw new MissingMethodException (Locale.GetText ("Default constructor not found for type " + FullName));
90 // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
92 throw new MissingMethodException (Locale.GetText ("Cannot create an abstract class '{0}'.", FullName));
95 return ctor.InternalInvoke (null, null);
98 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
101 var res = TryConvertToType (value, ref failed);
105 if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
106 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
108 if (binder != null && binder != Type.DefaultBinder)
109 return binder.ChangeType (value, this, culture);
111 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
114 object TryConvertToType (object value, ref bool failed)
116 if (IsInstanceOfType (value)) {
121 var elementType = GetElementType ();
122 if (value == null || elementType.IsInstanceOfType (value)) {
131 var type = Enum.GetUnderlyingType (this);
132 if (type == value.GetType ())
134 var res = IsConvertibleToPrimitiveType (value, this);
137 } else if (IsPrimitive) {
138 var res = IsConvertibleToPrimitiveType (value, this);
141 } else if (IsPointer) {
142 var vtype = value.GetType ();
143 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
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)
157 var type = value.GetType ();
159 type = Enum.GetUnderlyingType (type);
160 if (type == targetType)
164 var from = Type.GetTypeCode (type);
165 var to = Type.GetTypeCode (targetType);
171 return (Char) (Byte) value;
172 case TypeCode.UInt16:
179 return (Int16) (Byte) value;
181 return (Int16) (SByte) value;
184 case TypeCode.UInt16:
187 return (UInt16) (Byte) value;
195 return (Int32) (Byte) value;
197 return (Int32) (SByte) value;
199 return (Int32) (Char) value;
201 return (Int32) (Int16) value;
202 case TypeCode.UInt16:
203 return (Int32) (UInt16) value;
206 case TypeCode.UInt32:
209 return (UInt32) (Byte) value;
211 return (UInt32) (Char) value;
212 case TypeCode.UInt16:
213 return (UInt32) (UInt16) value;
219 return (Int64) (Byte) value;
221 return (Int64) (SByte) value;
223 return (Int64) (Int16) value;
225 return (Int64) (Char) value;
226 case TypeCode.UInt16:
227 return (Int64) (UInt16) value;
229 return (Int64) (Int32) value;
230 case TypeCode.UInt32:
231 return (Int64) (UInt32) value;
234 case TypeCode.UInt64:
237 return (UInt64) (Byte) value;
239 return (UInt64) (Char) value;
240 case TypeCode.UInt16:
241 return (UInt64) (UInt16) value;
242 case TypeCode.UInt32:
243 return (UInt64) (UInt32) value;
246 case TypeCode.Single:
249 return (Single) (Byte) value;
251 return (Single) (SByte) value;
253 return (Single) (Int16) value;
255 return (Single) (Char) value;
256 case TypeCode.UInt16:
257 return (Single) (UInt16) value;
259 return (Single) (Int32) value;
260 case TypeCode.UInt32:
261 return (Single) (UInt32) value;
263 return (Single) (Int64) value;
264 case TypeCode.UInt64:
265 return (Single) (UInt64) value;
268 case TypeCode.Double:
271 return (Double) (Byte) value;
273 return (Double) (SByte) value;
275 return (Double) (Char) value;
277 return (Double) (Int16) value;
278 case TypeCode.UInt16:
279 return (Double) (UInt16) value;
281 return (Double) (Int32) value;
282 case TypeCode.UInt32:
283 return (Double) (UInt32) value;
285 return (Double) (Int64) value;
286 case TypeCode.UInt64:
287 return (Double) (UInt64) value;
288 case TypeCode.Single:
289 return (Double) (Single) value;
294 // Everything else is rejected
298 [MethodImplAttribute(MethodImplOptions.InternalCall)]
299 extern Type make_array_type (int rank);
301 public override Type MakeArrayType ()
303 return make_array_type (0);
306 public override Type MakeArrayType (int rank)
308 if (rank < 1 || rank > 255)
309 throw new IndexOutOfRangeException ();
310 return make_array_type (rank);
313 [MethodImplAttribute(MethodImplOptions.InternalCall)]
314 extern Type make_byref_type ();
316 public override Type MakeByRefType ()
319 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
320 return make_byref_type ();
323 [MethodImplAttribute(MethodImplOptions.InternalCall)]
324 static extern Type MakePointerType (Type type);
326 public override Type MakePointerType ()
328 return MakePointerType (this);
331 public override StructLayoutAttribute StructLayoutAttribute {
333 return GetStructLayoutAttribute ();
337 public override bool ContainsGenericParameters {
339 if (IsGenericParameter)
343 foreach (Type arg in GetGenericArguments ())
344 if (arg.ContainsGenericParameters)
349 return GetElementType ().ContainsGenericParameters;
355 public override Type[] GetGenericParameterConstraints()
357 if (!IsGenericParameter)
358 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
359 Contract.EndContractBlock();
361 Type[] constraints = GetGenericParameterConstraints_impl ();
363 if (constraints == null)
364 constraints = EmptyArray<Type>.Value;
369 public override Type MakeGenericType (params Type[] typeArguments)
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");
380 bool hasUserType = false;
382 Type[] systemTypes = new Type[typeArguments.Length];
383 for (int i = 0; i < typeArguments.Length; ++i) {
384 Type t = typeArguments [i];
386 throw new ArgumentNullException ("typeArguments");
388 if (!(t is MonoType))
395 throw new NotSupportedException ("User types are not supported under full aot");
397 return new MonoGenericClass (this, typeArguments);
401 Type res = MakeGenericType (this, systemTypes);
403 throw new TypeLoadException ();
407 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408 static extern Type MakeGenericType (Type gt, Type [] types);
410 [MethodImplAttribute(MethodImplOptions.InternalCall)]
411 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
413 [MethodImplAttribute(MethodImplOptions.InternalCall)]
414 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
416 [MethodImplAttribute(MethodImplOptions.InternalCall)]
417 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
419 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
421 if (IsGenericParameter)
422 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
424 if ((object)ifaceType == null)
425 throw new ArgumentNullException("ifaceType");
426 Contract.EndContractBlock();
428 RuntimeType ifaceRtType = ifaceType as RuntimeType;
430 if (ifaceRtType == null)
431 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
433 InterfaceMapping res;
434 if (!ifaceType.IsInterface)
435 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
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");
447 [MethodImplAttribute(MethodImplOptions.InternalCall)]
448 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
450 public override Guid GUID {
452 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
455 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
459 StructLayoutAttribute GetStructLayoutAttribute ()
463 if (IsLayoutSequential)
464 kind = LayoutKind.Sequential;
465 else if (IsExplicitLayout)
466 kind = LayoutKind.Explicit;
468 kind = LayoutKind.Auto;
470 StructLayoutAttribute attr = new StructLayoutAttribute (kind);
473 attr.CharSet = CharSet.Unicode;
474 else if (IsAnsiClass)
475 attr.CharSet = CharSet.Ansi;
477 attr.CharSet = CharSet.Auto;
479 if (kind != LayoutKind.Auto) {
481 GetPacking (out packing, out attr.Size);
482 // 0 means no data provided, we end up with default value
490 [MethodImplAttribute(MethodImplOptions.InternalCall)]
491 extern void GetPacking (out int packing, out int size);
494 private static Dictionary<Guid, Type> clsid_types;
495 private static AssemblyBuilder clsid_assemblybuilder;
498 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
503 if (clsid_types == null)
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);
511 if (clsid_types.TryGetValue(clsid, out result))
514 if (clsid_assemblybuilder == null)
516 AssemblyName assemblyname = new AssemblyName ();
517 assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
518 clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
519 assemblyname, AssemblyBuilderAccess.Run);
521 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
524 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
525 TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
527 Type[] guidattrtypes = new Type[] { typeof(string) };
529 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
530 typeof(GuidAttribute).GetConstructor (guidattrtypes),
531 new object[] { clsid.ToString () });
533 typebuilder.SetCustomAttribute (customattr);
535 customattr = new CustomAttributeBuilder (
536 typeof(ComImportAttribute).GetConstructor (EmptyTypes),
539 typebuilder.SetCustomAttribute (customattr);
541 result = typebuilder.CreateType ();
543 clsid_types.Add(clsid, result);
548 throw new NotImplementedException ("Unmanaged activation removed");
552 protected override TypeCode GetTypeCodeImpl ()
554 return GetTypeCodeImplInternal (this);
557 [MethodImplAttribute(MethodImplOptions.InternalCall)]
558 extern static TypeCode GetTypeCodeImplInternal (Type type);
560 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
562 throw new NotImplementedException ("Unmanaged activation is not supported");
565 public override string ToString()
567 return getFullName (false, false);
570 bool IsGenericCOMObjectImpl ()
575 [MethodImplAttribute (MethodImplOptions.InternalCall)]
576 static extern object CreateInstanceInternal (Type type);
578 public extern override MethodBase DeclaringMethod {
579 [MethodImplAttribute(MethodImplOptions.InternalCall)]
583 [MethodImplAttribute(MethodImplOptions.InternalCall)]
584 internal extern string getFullName(bool full_name, bool assembly_qualified);
586 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587 public extern override Type [] GetGenericArguments ();
589 [MethodImplAttribute(MethodImplOptions.InternalCall)]
590 extern GenericParameterAttributes GetGenericParameterAttributes ();
592 [MethodImplAttribute(MethodImplOptions.InternalCall)]
593 extern Type[] GetGenericParameterConstraints_impl ();
595 [MethodImplAttribute(MethodImplOptions.InternalCall)]
596 extern int GetGenericParameterPosition ();
598 [MethodImplAttribute(MethodImplOptions.InternalCall)]
599 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
601 [MethodImplAttribute(MethodImplOptions.InternalCall)]
602 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
604 [MethodImplAttribute(MethodImplOptions.InternalCall)]
605 public extern override Type[] GetInterfaces();
607 [MethodImplAttribute(MethodImplOptions.InternalCall)]
608 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);
610 public override string AssemblyQualifiedName {
612 return getFullName (true, true);
616 public extern override Type DeclaringType {
617 [MethodImplAttribute(MethodImplOptions.InternalCall)]
621 public override string FullName {
623 throw new NotImplementedException ();
627 public extern override string Name {
628 [MethodImplAttribute(MethodImplOptions.InternalCall)]
632 public extern override string Namespace {
633 [MethodImplAttribute(MethodImplOptions.InternalCall)]
637 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
638 [MethodImplAttribute(MethodImplOptions.InternalCall)]
639 public extern int get_core_clr_security_level ();
641 public override bool IsSecurityTransparent {
642 get { return get_core_clr_security_level () == 0; }
645 public override bool IsSecurityCritical {
646 get { return get_core_clr_security_level () > 0; }
649 public override bool IsSecuritySafeCritical {
650 get { return get_core_clr_security_level () == 1; }