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 var paramInfo = new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this));
456 Type[] constraints = paramInfo.Constraints;
458 if (constraints == null)
459 constraints = EmptyArray<Type>.Value;
464 internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
466 var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
467 var ctor = gt.GetDefaultConstructor ();
468 return ctor.InternalInvoke (null, null);
471 [MethodImplAttribute(MethodImplOptions.InternalCall)]
472 static extern Type MakeGenericType (Type gt, Type [] types);
474 [MethodImplAttribute(MethodImplOptions.InternalCall)]
475 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
477 [MethodImplAttribute(MethodImplOptions.InternalCall)]
478 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
480 [MethodImplAttribute(MethodImplOptions.InternalCall)]
481 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
483 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
485 if (IsGenericParameter)
486 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
488 if ((object)ifaceType == null)
489 throw new ArgumentNullException("ifaceType");
490 Contract.EndContractBlock();
492 RuntimeType ifaceRtType = ifaceType as RuntimeType;
494 if (ifaceRtType == null)
495 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
497 InterfaceMapping res;
498 if (!ifaceType.IsInterface)
499 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
501 throw new ArgumentException ("'this' type cannot be an interface itself");
502 res.TargetType = this;
503 res.InterfaceType = ifaceType;
504 GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
505 if (res.TargetMethods == null)
506 throw new ArgumentException (Locale.GetText ("Interface not found"), "ifaceType");
511 [MethodImplAttribute(MethodImplOptions.InternalCall)]
512 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
514 public override Guid GUID {
516 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
519 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
523 [MethodImplAttribute(MethodImplOptions.InternalCall)]
524 internal extern void GetPacking (out int packing, out int size);
527 private static Dictionary<Guid, Type> clsid_types;
528 private static AssemblyBuilder clsid_assemblybuilder;
531 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
536 if (clsid_types == null)
538 Dictionary<Guid, Type> new_clsid_types = new Dictionary<Guid, Type> ();
539 Interlocked.CompareExchange<Dictionary<Guid, Type>>(
540 ref clsid_types, new_clsid_types, null);
544 if (clsid_types.TryGetValue(clsid, out result))
547 if (clsid_assemblybuilder == null)
549 AssemblyName assemblyname = new AssemblyName ();
550 assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
551 clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
552 assemblyname, AssemblyBuilderAccess.Run);
554 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
557 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
558 TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
560 Type[] guidattrtypes = new Type[] { typeof(string) };
562 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
563 typeof(GuidAttribute).GetConstructor (guidattrtypes),
564 new object[] { clsid.ToString () });
566 typebuilder.SetCustomAttribute (customattr);
568 customattr = new CustomAttributeBuilder (
569 typeof(ComImportAttribute).GetConstructor (EmptyTypes),
572 typebuilder.SetCustomAttribute (customattr);
574 result = typebuilder.CreateType ();
576 clsid_types.Add(clsid, result);
581 throw new NotImplementedException ("Unmanaged activation removed");
585 protected override TypeCode GetTypeCodeImpl ()
587 return GetTypeCodeImplInternal (this);
590 [MethodImplAttribute(MethodImplOptions.InternalCall)]
591 extern static TypeCode GetTypeCodeImplInternal (Type type);
593 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
595 throw new NotImplementedException ("Unmanaged activation is not supported");
598 public override string ToString()
600 return getFullName (false, false);
603 bool IsGenericCOMObjectImpl ()
608 [MethodImplAttribute (MethodImplOptions.InternalCall)]
609 static extern object CreateInstanceInternal (Type type);
611 public extern override MethodBase DeclaringMethod {
612 [MethodImplAttribute(MethodImplOptions.InternalCall)]
616 [MethodImplAttribute(MethodImplOptions.InternalCall)]
617 internal extern string getFullName(bool full_name, bool assembly_qualified);
619 [MethodImplAttribute(MethodImplOptions.InternalCall)]
620 extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
622 GenericParameterAttributes GetGenericParameterAttributes () {
623 return (new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this))).Attributes;
626 [MethodImplAttribute(MethodImplOptions.InternalCall)]
627 extern int GetGenericParameterPosition ();
629 [MethodImplAttribute(MethodImplOptions.InternalCall)]
630 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
632 [MethodImplAttribute(MethodImplOptions.InternalCall)]
633 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
635 [MethodImplAttribute(MethodImplOptions.InternalCall)]
636 public extern override Type[] GetInterfaces();
638 [MethodImplAttribute(MethodImplOptions.InternalCall)]
639 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);
641 public override string AssemblyQualifiedName {
643 return getFullName (true, true);
647 public extern override Type DeclaringType {
648 [MethodImplAttribute(MethodImplOptions.InternalCall)]
652 public extern override string Name {
653 [MethodImplAttribute(MethodImplOptions.InternalCall)]
657 public extern override string Namespace {
658 [MethodImplAttribute(MethodImplOptions.InternalCall)]
663 static int get_core_clr_security_level ()
668 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
669 [MethodImplAttribute(MethodImplOptions.InternalCall)]
670 public extern int get_core_clr_security_level ();
672 public override bool IsSecurityTransparent {
673 get { return get_core_clr_security_level () == 0; }
676 public override bool IsSecurityCritical {
677 get { return get_core_clr_security_level () > 0; }
680 public override bool IsSecuritySafeCritical {
681 get { return get_core_clr_security_level () == 1; }
685 public override int GetHashCode()
687 Type t = UnderlyingSystemType;
688 if (t != null && t != this)
689 return t.GetHashCode ();
690 return (int)_impl.Value;
693 public override string FullName {
696 // This doesn't need locking
697 if (type_info == null)
698 type_info = new MonoTypeInfo ();
699 if ((fullName = type_info.full_name) == null)
700 fullName = type_info.full_name = getFullName (true, false);
706 internal override bool IsUserType {