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 [MethodImplAttribute(MethodImplOptions.InternalCall)]
63 private static extern void type_from_obj (RuntimeType type, Object obj);
65 internal RuntimeType (Object obj)
67 // this should not be used - lupus
68 type_from_obj (this, obj);
70 throw new NotImplementedException ();
73 internal MonoCMethod GetDefaultConstructor ()
75 MonoCMethod ctor = null;
77 if (type_info == null)
78 type_info = new MonoTypeInfo ();
80 ctor = type_info.default_ctor;
83 var ctors = GetConstructors (BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
85 for (int i = 0; i < ctors.Length; ++i) {
86 if (ctors [i].GetParametersCount () == 0) {
87 type_info.default_ctor = ctor = (MonoCMethod) ctors [i];
96 [MethodImplAttribute(MethodImplOptions.InternalCall)]
97 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
99 [MethodImplAttribute(MethodImplOptions.InternalCall)]
100 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
102 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
104 if (fromNoninstanciated == null)
105 throw new ArgumentNullException ("fromNoninstanciated");
106 return GetCorrespondingInflatedMethod (fromNoninstanciated);
109 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
111 if (fromNoninstanciated == null)
112 throw new ArgumentNullException ("fromNoninstanciated");
113 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
116 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
118 /* create sensible flags from given FieldInfo */
119 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
120 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
121 return GetField (fromNoninstanciated.Name, flags);
124 string GetDefaultMemberName ()
126 object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
127 return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
130 RuntimeConstructorInfo m_serializationCtor;
131 internal RuntimeConstructorInfo GetSerializationCtor()
133 if (m_serializationCtor == null) {
134 var s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
136 m_serializationCtor = GetConstructor(
137 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
139 CallingConventions.Any,
141 null) as RuntimeConstructorInfo;
144 return m_serializationCtor;
147 internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
149 bool bNeedSecurityCheck = true;
150 bool bCanBeCached = false;
151 bool bSecurityCheckOff = false;
154 CreateInstanceCheckThis();
157 bSecurityCheckOff = true;
159 return CreateInstanceMono (!publicOnly);
162 object CreateInstanceMono (bool nonPublic)
164 var ctor = GetDefaultConstructor ();
165 if (!nonPublic && ctor != null && !ctor.IsPublic) {
170 Type elementType = this.GetRootElementType();
171 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
172 throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
175 return CreateInstanceInternal (this);
177 throw new MissingMethodException (Locale.GetText ("Default constructor not found for type " + FullName));
180 // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
182 throw new MissingMethodException (Locale.GetText ("Cannot create an abstract class '{0}'.", FullName));
185 return ctor.InternalInvoke (null, null);
188 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
191 var res = TryConvertToType (value, ref failed);
195 if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
196 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
198 if (binder != null && binder != Type.DefaultBinder)
199 return binder.ChangeType (value, this, culture);
201 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
204 object TryConvertToType (object value, ref bool failed)
206 if (IsInstanceOfType (value)) {
211 var elementType = GetElementType ();
212 if (value == null || elementType.IsInstanceOfType (value)) {
221 var type = Enum.GetUnderlyingType (this);
222 if (type == value.GetType ())
224 var res = IsConvertibleToPrimitiveType (value, this);
227 } else if (IsPrimitive) {
228 var res = IsConvertibleToPrimitiveType (value, this);
231 } else if (IsPointer) {
232 var vtype = value.GetType ();
233 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
241 // Binder uses some incompatible conversion rules. For example
242 // int value cannot be used with decimal parameter but in other
243 // ways it's more flexible than normal convertor, for example
244 // long value can be used with int based enum
245 static object IsConvertibleToPrimitiveType (object value, Type targetType)
247 var type = value.GetType ();
249 type = Enum.GetUnderlyingType (type);
250 if (type == targetType)
254 var from = Type.GetTypeCode (type);
255 var to = Type.GetTypeCode (targetType);
261 return (Char) (Byte) value;
262 case TypeCode.UInt16:
269 return (Int16) (Byte) value;
271 return (Int16) (SByte) value;
274 case TypeCode.UInt16:
277 return (UInt16) (Byte) value;
285 return (Int32) (Byte) value;
287 return (Int32) (SByte) value;
289 return (Int32) (Char) value;
291 return (Int32) (Int16) value;
292 case TypeCode.UInt16:
293 return (Int32) (UInt16) value;
296 case TypeCode.UInt32:
299 return (UInt32) (Byte) value;
301 return (UInt32) (Char) value;
302 case TypeCode.UInt16:
303 return (UInt32) (UInt16) value;
309 return (Int64) (Byte) value;
311 return (Int64) (SByte) value;
313 return (Int64) (Int16) value;
315 return (Int64) (Char) value;
316 case TypeCode.UInt16:
317 return (Int64) (UInt16) value;
319 return (Int64) (Int32) value;
320 case TypeCode.UInt32:
321 return (Int64) (UInt32) value;
324 case TypeCode.UInt64:
327 return (UInt64) (Byte) value;
329 return (UInt64) (Char) value;
330 case TypeCode.UInt16:
331 return (UInt64) (UInt16) value;
332 case TypeCode.UInt32:
333 return (UInt64) (UInt32) value;
336 case TypeCode.Single:
339 return (Single) (Byte) value;
341 return (Single) (SByte) value;
343 return (Single) (Int16) value;
345 return (Single) (Char) value;
346 case TypeCode.UInt16:
347 return (Single) (UInt16) value;
349 return (Single) (Int32) value;
350 case TypeCode.UInt32:
351 return (Single) (UInt32) value;
353 return (Single) (Int64) value;
354 case TypeCode.UInt64:
355 return (Single) (UInt64) value;
358 case TypeCode.Double:
361 return (Double) (Byte) value;
363 return (Double) (SByte) value;
365 return (Double) (Char) value;
367 return (Double) (Int16) value;
368 case TypeCode.UInt16:
369 return (Double) (UInt16) value;
371 return (Double) (Int32) value;
372 case TypeCode.UInt32:
373 return (Double) (UInt32) value;
375 return (Double) (Int64) value;
376 case TypeCode.UInt64:
377 return (Double) (UInt64) value;
378 case TypeCode.Single:
379 return (Double) (Single) value;
384 // Everything else is rejected
388 string GetCachedName (TypeNameKind kind)
391 case TypeNameKind.SerializationName:
394 throw new NotImplementedException ();
398 [MethodImplAttribute(MethodImplOptions.InternalCall)]
399 extern Type make_array_type (int rank);
401 public override Type MakeArrayType ()
403 return make_array_type (0);
406 public override Type MakeArrayType (int rank)
408 if (rank < 1 || rank > 255)
409 throw new IndexOutOfRangeException ();
410 return make_array_type (rank);
413 [MethodImplAttribute(MethodImplOptions.InternalCall)]
414 extern Type make_byref_type ();
416 public override Type MakeByRefType ()
419 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
420 return make_byref_type ();
423 [MethodImplAttribute(MethodImplOptions.InternalCall)]
424 static extern Type MakePointerType (Type type);
426 public override Type MakePointerType ()
428 return MakePointerType (this);
431 public override StructLayoutAttribute StructLayoutAttribute {
433 return StructLayoutAttribute.GetCustomAttribute (this);
437 public override bool ContainsGenericParameters {
439 if (IsGenericParameter)
443 foreach (Type arg in GetGenericArguments ())
444 if (arg.ContainsGenericParameters)
449 return GetElementType ().ContainsGenericParameters;
455 public override Type[] GetGenericParameterConstraints()
457 if (!IsGenericParameter)
458 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
459 Contract.EndContractBlock();
461 Type[] constraints = GetGenericParameterConstraints_impl ();
463 if (constraints == null)
464 constraints = EmptyArray<Type>.Value;
469 internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
471 var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
472 var ctor = gt.GetDefaultConstructor ();
473 return ctor.InternalInvoke (null, null);
476 [MethodImplAttribute(MethodImplOptions.InternalCall)]
477 static extern Type MakeGenericType (Type gt, Type [] types);
479 [MethodImplAttribute(MethodImplOptions.InternalCall)]
480 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
482 [MethodImplAttribute(MethodImplOptions.InternalCall)]
483 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
485 [MethodImplAttribute(MethodImplOptions.InternalCall)]
486 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
488 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
490 if (IsGenericParameter)
491 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
493 if ((object)ifaceType == null)
494 throw new ArgumentNullException("ifaceType");
495 Contract.EndContractBlock();
497 RuntimeType ifaceRtType = ifaceType as RuntimeType;
499 if (ifaceRtType == null)
500 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
502 InterfaceMapping res;
503 if (!ifaceType.IsInterface)
504 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
506 throw new ArgumentException ("'this' type cannot be an interface itself");
507 res.TargetType = this;
508 res.InterfaceType = ifaceType;
509 GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
510 if (res.TargetMethods == null)
511 throw new ArgumentException (Locale.GetText ("Interface not found"), "ifaceType");
516 [MethodImplAttribute(MethodImplOptions.InternalCall)]
517 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
519 public override Guid GUID {
521 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
524 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
528 [MethodImplAttribute(MethodImplOptions.InternalCall)]
529 internal extern void GetPacking (out int packing, out int size);
532 private static Dictionary<Guid, Type> clsid_types;
533 private static AssemblyBuilder clsid_assemblybuilder;
536 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
541 if (clsid_types == null)
543 Dictionary<Guid, Type> new_clsid_types = new Dictionary<Guid, Type> ();
544 Interlocked.CompareExchange<Dictionary<Guid, Type>>(
545 ref clsid_types, new_clsid_types, null);
549 if (clsid_types.TryGetValue(clsid, out result))
552 if (clsid_assemblybuilder == null)
554 AssemblyName assemblyname = new AssemblyName ();
555 assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
556 clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
557 assemblyname, AssemblyBuilderAccess.Run);
559 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
562 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
563 TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
565 Type[] guidattrtypes = new Type[] { typeof(string) };
567 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
568 typeof(GuidAttribute).GetConstructor (guidattrtypes),
569 new object[] { clsid.ToString () });
571 typebuilder.SetCustomAttribute (customattr);
573 customattr = new CustomAttributeBuilder (
574 typeof(ComImportAttribute).GetConstructor (EmptyTypes),
577 typebuilder.SetCustomAttribute (customattr);
579 result = typebuilder.CreateType ();
581 clsid_types.Add(clsid, result);
586 throw new NotImplementedException ("Unmanaged activation removed");
590 protected override TypeCode GetTypeCodeImpl ()
592 return GetTypeCodeImplInternal (this);
595 [MethodImplAttribute(MethodImplOptions.InternalCall)]
596 extern static TypeCode GetTypeCodeImplInternal (Type type);
598 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
600 throw new NotImplementedException ("Unmanaged activation is not supported");
603 public override string ToString()
605 return getFullName (false, false);
608 bool IsGenericCOMObjectImpl ()
613 [MethodImplAttribute (MethodImplOptions.InternalCall)]
614 static extern object CreateInstanceInternal (Type type);
616 public extern override MethodBase DeclaringMethod {
617 [MethodImplAttribute(MethodImplOptions.InternalCall)]
621 [MethodImplAttribute(MethodImplOptions.InternalCall)]
622 internal extern string getFullName(bool full_name, bool assembly_qualified);
624 [MethodImplAttribute(MethodImplOptions.InternalCall)]
625 extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
627 [MethodImplAttribute(MethodImplOptions.InternalCall)]
628 extern GenericParameterAttributes GetGenericParameterAttributes ();
630 [MethodImplAttribute(MethodImplOptions.InternalCall)]
631 extern Type[] GetGenericParameterConstraints_impl ();
633 [MethodImplAttribute(MethodImplOptions.InternalCall)]
634 extern int GetGenericParameterPosition ();
636 [MethodImplAttribute(MethodImplOptions.InternalCall)]
637 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
639 [MethodImplAttribute(MethodImplOptions.InternalCall)]
640 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
642 [MethodImplAttribute(MethodImplOptions.InternalCall)]
643 public extern override Type[] GetInterfaces();
645 [MethodImplAttribute(MethodImplOptions.InternalCall)]
646 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);
648 public override string AssemblyQualifiedName {
650 return getFullName (true, true);
654 public extern override Type DeclaringType {
655 [MethodImplAttribute(MethodImplOptions.InternalCall)]
659 public extern override string Name {
660 [MethodImplAttribute(MethodImplOptions.InternalCall)]
664 public extern override string Namespace {
665 [MethodImplAttribute(MethodImplOptions.InternalCall)]
670 static int get_core_clr_security_level ()
675 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
676 [MethodImplAttribute(MethodImplOptions.InternalCall)]
677 public extern int get_core_clr_security_level ();
679 public override bool IsSecurityTransparent {
680 get { return get_core_clr_security_level () == 0; }
683 public override bool IsSecurityCritical {
684 get { return get_core_clr_security_level () > 0; }
687 public override bool IsSecuritySafeCritical {
688 get { return get_core_clr_security_level () == 1; }
692 public override int GetHashCode()
694 Type t = UnderlyingSystemType;
695 if (t != null && t != this)
696 return t.GetHashCode ();
697 return (int)_impl.Value;
700 public override string FullName {
703 // This doesn't need locking
704 if (type_info == null)
705 type_info = new MonoTypeInfo ();
706 if ((fullName = type_info.full_name) == null)
707 fullName = type_info.full_name = getFullName (true, false);
713 internal override bool IsUserType {