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;
40 using System.Runtime.Serialization;
44 // Contains information about the type which is expensive to compute
45 [StructLayout (LayoutKind.Sequential)]
46 internal class MonoTypeInfo {
47 // this is the displayed form: special characters
48 // ,+*&*[]\ in the identifier portions of the names
49 // have been escaped with a leading backslash (\)
50 public string full_name;
51 public MonoCMethod default_ctor;
54 [StructLayout (LayoutKind.Sequential)]
55 partial class RuntimeType
58 MonoTypeInfo type_info;
60 internal Object GenericCache;
62 internal RuntimeType (Object obj)
64 throw new NotImplementedException ();
67 internal MonoCMethod GetDefaultConstructor ()
69 MonoCMethod ctor = null;
71 if (type_info == null)
72 type_info = new MonoTypeInfo ();
74 ctor = type_info.default_ctor;
77 var ctors = GetConstructors (BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
79 for (int i = 0; i < ctors.Length; ++i) {
80 if (ctors [i].GetParametersCount () == 0) {
81 type_info.default_ctor = ctor = (MonoCMethod) ctors [i];
90 [MethodImplAttribute(MethodImplOptions.InternalCall)]
91 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
93 [MethodImplAttribute(MethodImplOptions.InternalCall)]
94 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
96 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
98 if (fromNoninstanciated == null)
99 throw new ArgumentNullException ("fromNoninstanciated");
100 return GetCorrespondingInflatedMethod (fromNoninstanciated);
103 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
105 if (fromNoninstanciated == null)
106 throw new ArgumentNullException ("fromNoninstanciated");
107 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
110 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
112 /* create sensible flags from given FieldInfo */
113 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
114 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
115 return GetField (fromNoninstanciated.Name, flags);
118 string GetDefaultMemberName ()
120 object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
121 return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
124 RuntimeConstructorInfo m_serializationCtor;
125 internal RuntimeConstructorInfo GetSerializationCtor()
127 if (m_serializationCtor == null) {
128 var s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
130 m_serializationCtor = GetConstructor(
131 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
133 CallingConventions.Any,
135 null) as RuntimeConstructorInfo;
138 return m_serializationCtor;
141 internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
143 bool bNeedSecurityCheck = true;
144 bool bCanBeCached = false;
145 bool bSecurityCheckOff = false;
148 CreateInstanceCheckThis();
151 bSecurityCheckOff = true;
153 return CreateInstanceMono (!publicOnly);
156 object CreateInstanceMono (bool nonPublic)
158 var ctor = GetDefaultConstructor ();
159 if (!nonPublic && ctor != null && !ctor.IsPublic) {
164 Type elementType = this.GetRootElementType();
165 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
166 throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
169 return CreateInstanceInternal (this);
171 throw new MissingMethodException (Locale.GetText ("Default constructor not found for type " + FullName));
174 // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
176 throw new MissingMethodException (Locale.GetText ("Cannot create an abstract class '{0}'.", FullName));
179 return ctor.InternalInvoke (null, null);
182 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
185 var res = TryConvertToType (value, ref failed);
189 if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
190 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
192 if (binder != null && binder != Type.DefaultBinder)
193 return binder.ChangeType (value, this, culture);
195 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
198 object TryConvertToType (object value, ref bool failed)
200 if (IsInstanceOfType (value)) {
205 var elementType = GetElementType ();
206 if (value == null || elementType.IsInstanceOfType (value)) {
215 var type = Enum.GetUnderlyingType (this);
216 if (type == value.GetType ())
218 var res = IsConvertibleToPrimitiveType (value, this);
221 } else if (IsPrimitive) {
222 var res = IsConvertibleToPrimitiveType (value, this);
225 } else if (IsPointer) {
226 var vtype = value.GetType ();
227 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
235 // Binder uses some incompatible conversion rules. For example
236 // int value cannot be used with decimal parameter but in other
237 // ways it's more flexible than normal convertor, for example
238 // long value can be used with int based enum
239 static object IsConvertibleToPrimitiveType (object value, Type targetType)
241 var type = value.GetType ();
243 type = Enum.GetUnderlyingType (type);
244 if (type == targetType)
248 var from = Type.GetTypeCode (type);
249 var to = Type.GetTypeCode (targetType);
255 return (Char) (Byte) value;
256 case TypeCode.UInt16:
263 return (Int16) (Byte) value;
265 return (Int16) (SByte) value;
268 case TypeCode.UInt16:
271 return (UInt16) (Byte) value;
279 return (Int32) (Byte) value;
281 return (Int32) (SByte) value;
283 return (Int32) (Char) value;
285 return (Int32) (Int16) value;
286 case TypeCode.UInt16:
287 return (Int32) (UInt16) value;
290 case TypeCode.UInt32:
293 return (UInt32) (Byte) value;
295 return (UInt32) (Char) value;
296 case TypeCode.UInt16:
297 return (UInt32) (UInt16) value;
303 return (Int64) (Byte) value;
305 return (Int64) (SByte) value;
307 return (Int64) (Int16) value;
309 return (Int64) (Char) value;
310 case TypeCode.UInt16:
311 return (Int64) (UInt16) value;
313 return (Int64) (Int32) value;
314 case TypeCode.UInt32:
315 return (Int64) (UInt32) value;
318 case TypeCode.UInt64:
321 return (UInt64) (Byte) value;
323 return (UInt64) (Char) value;
324 case TypeCode.UInt16:
325 return (UInt64) (UInt16) value;
326 case TypeCode.UInt32:
327 return (UInt64) (UInt32) value;
330 case TypeCode.Single:
333 return (Single) (Byte) value;
335 return (Single) (SByte) value;
337 return (Single) (Int16) value;
339 return (Single) (Char) value;
340 case TypeCode.UInt16:
341 return (Single) (UInt16) value;
343 return (Single) (Int32) value;
344 case TypeCode.UInt32:
345 return (Single) (UInt32) value;
347 return (Single) (Int64) value;
348 case TypeCode.UInt64:
349 return (Single) (UInt64) value;
352 case TypeCode.Double:
355 return (Double) (Byte) value;
357 return (Double) (SByte) value;
359 return (Double) (Char) value;
361 return (Double) (Int16) value;
362 case TypeCode.UInt16:
363 return (Double) (UInt16) value;
365 return (Double) (Int32) value;
366 case TypeCode.UInt32:
367 return (Double) (UInt32) value;
369 return (Double) (Int64) value;
370 case TypeCode.UInt64:
371 return (Double) (UInt64) value;
372 case TypeCode.Single:
373 return (Double) (Single) value;
378 // Everything else is rejected
382 string GetCachedName (TypeNameKind kind)
385 case TypeNameKind.SerializationName:
388 throw new NotImplementedException ();
392 [MethodImplAttribute(MethodImplOptions.InternalCall)]
393 extern Type make_array_type (int rank);
395 public override Type MakeArrayType ()
397 return make_array_type (0);
400 public override Type MakeArrayType (int rank)
402 if (rank < 1 || rank > 255)
403 throw new IndexOutOfRangeException ();
404 return make_array_type (rank);
407 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408 extern Type make_byref_type ();
410 public override Type MakeByRefType ()
413 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
414 return make_byref_type ();
417 [MethodImplAttribute(MethodImplOptions.InternalCall)]
418 static extern Type MakePointerType (Type type);
420 public override Type MakePointerType ()
422 return MakePointerType (this);
425 public override StructLayoutAttribute StructLayoutAttribute {
427 return StructLayoutAttribute.GetCustomAttribute (this);
431 public override bool ContainsGenericParameters {
433 if (IsGenericParameter)
437 foreach (Type arg in GetGenericArguments ())
438 if (arg.ContainsGenericParameters)
443 return GetElementType ().ContainsGenericParameters;
449 public override Type[] GetGenericParameterConstraints()
451 if (!IsGenericParameter)
452 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
453 Contract.EndContractBlock();
455 Type[] constraints = GetGenericParameterConstraints_impl ();
457 if (constraints == null)
458 constraints = EmptyArray<Type>.Value;
463 internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
465 var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
466 var ctor = gt.GetDefaultConstructor ();
467 return ctor.InternalInvoke (null, null);
470 [MethodImplAttribute(MethodImplOptions.InternalCall)]
471 static extern Type MakeGenericType (Type gt, Type [] types);
473 [MethodImplAttribute(MethodImplOptions.InternalCall)]
474 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
476 [MethodImplAttribute(MethodImplOptions.InternalCall)]
477 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
479 [MethodImplAttribute(MethodImplOptions.InternalCall)]
480 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
482 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
484 if (IsGenericParameter)
485 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
487 if ((object)ifaceType == null)
488 throw new ArgumentNullException("ifaceType");
489 Contract.EndContractBlock();
491 RuntimeType ifaceRtType = ifaceType as RuntimeType;
493 if (ifaceRtType == null)
494 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
496 InterfaceMapping res;
497 if (!ifaceType.IsInterface)
498 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
500 throw new ArgumentException ("'this' type cannot be an interface itself");
501 res.TargetType = this;
502 res.InterfaceType = ifaceType;
503 GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
504 if (res.TargetMethods == null)
505 throw new ArgumentException (Locale.GetText ("Interface not found"), "ifaceType");
510 [MethodImplAttribute(MethodImplOptions.InternalCall)]
511 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
513 public override Guid GUID {
515 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
518 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
522 [MethodImplAttribute(MethodImplOptions.InternalCall)]
523 internal extern void GetPacking (out int packing, out int size);
526 private static Dictionary<Guid, Type> clsid_types;
527 private static AssemblyBuilder clsid_assemblybuilder;
530 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
535 if (clsid_types == null)
537 Dictionary<Guid, Type> new_clsid_types = new Dictionary<Guid, Type> ();
538 Interlocked.CompareExchange<Dictionary<Guid, Type>>(
539 ref clsid_types, new_clsid_types, null);
543 if (clsid_types.TryGetValue(clsid, out result))
546 if (clsid_assemblybuilder == null)
548 AssemblyName assemblyname = new AssemblyName ();
549 assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
550 clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
551 assemblyname, AssemblyBuilderAccess.Run);
553 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
556 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
557 TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
559 Type[] guidattrtypes = new Type[] { typeof(string) };
561 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
562 typeof(GuidAttribute).GetConstructor (guidattrtypes),
563 new object[] { clsid.ToString () });
565 typebuilder.SetCustomAttribute (customattr);
567 customattr = new CustomAttributeBuilder (
568 typeof(ComImportAttribute).GetConstructor (EmptyTypes),
571 typebuilder.SetCustomAttribute (customattr);
573 result = typebuilder.CreateType ();
575 clsid_types.Add(clsid, result);
580 throw new NotImplementedException ("Unmanaged activation removed");
584 protected override TypeCode GetTypeCodeImpl ()
586 return GetTypeCodeImplInternal (this);
589 [MethodImplAttribute(MethodImplOptions.InternalCall)]
590 extern static TypeCode GetTypeCodeImplInternal (Type type);
592 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
594 throw new NotImplementedException ("Unmanaged activation is not supported");
597 public override string ToString()
599 return getFullName (false, false);
602 bool IsGenericCOMObjectImpl ()
607 [MethodImplAttribute (MethodImplOptions.InternalCall)]
608 static extern object CreateInstanceInternal (Type type);
610 public extern override MethodBase DeclaringMethod {
611 [MethodImplAttribute(MethodImplOptions.InternalCall)]
615 [MethodImplAttribute(MethodImplOptions.InternalCall)]
616 internal extern string getFullName(bool full_name, bool assembly_qualified);
618 [MethodImplAttribute(MethodImplOptions.InternalCall)]
619 extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
621 [MethodImplAttribute(MethodImplOptions.InternalCall)]
622 extern GenericParameterAttributes GetGenericParameterAttributes ();
624 [MethodImplAttribute(MethodImplOptions.InternalCall)]
625 extern Type[] GetGenericParameterConstraints_impl ();
627 [MethodImplAttribute(MethodImplOptions.InternalCall)]
628 extern int GetGenericParameterPosition ();
630 [MethodImplAttribute(MethodImplOptions.InternalCall)]
631 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
633 [MethodImplAttribute(MethodImplOptions.InternalCall)]
634 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
636 [MethodImplAttribute(MethodImplOptions.InternalCall)]
637 public extern override Type[] GetInterfaces();
639 [MethodImplAttribute(MethodImplOptions.InternalCall)]
640 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);
642 public override string AssemblyQualifiedName {
644 return getFullName (true, true);
648 public extern override Type DeclaringType {
649 [MethodImplAttribute(MethodImplOptions.InternalCall)]
653 public extern override string Name {
654 [MethodImplAttribute(MethodImplOptions.InternalCall)]
658 public extern override string Namespace {
659 [MethodImplAttribute(MethodImplOptions.InternalCall)]
664 static int get_core_clr_security_level ()
669 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
670 [MethodImplAttribute(MethodImplOptions.InternalCall)]
671 public extern int get_core_clr_security_level ();
673 public override bool IsSecurityTransparent {
674 get { return get_core_clr_security_level () == 0; }
677 public override bool IsSecurityCritical {
678 get { return get_core_clr_security_level () > 0; }
681 public override bool IsSecuritySafeCritical {
682 get { return get_core_clr_security_level () == 1; }
686 public override int GetHashCode()
688 Type t = UnderlyingSystemType;
689 if (t != null && t != this)
690 return t.GetHashCode ();
691 return (int)_impl.Value;
694 public override string FullName {
697 // This doesn't need locking
698 if (type_info == null)
699 type_info = new MonoTypeInfo ();
700 if ((fullName = type_info.full_name) == null)
701 fullName = type_info.full_name = getFullName (true, false);
707 internal override bool IsUserType {