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 partial class RuntimeType
46 internal virtual MonoCMethod GetDefaultConstructor ()
48 // TODO: Requires MonoType
49 throw new NotSupportedException ();
52 string GetDefaultMemberName ()
54 object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
55 return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
58 RuntimeConstructorInfo m_serializationCtor;
59 internal RuntimeConstructorInfo GetSerializationCtor()
61 if (m_serializationCtor == null) {
62 var s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
64 m_serializationCtor = GetConstructor(
65 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
67 CallingConventions.Any,
69 null) as RuntimeConstructorInfo;
72 return m_serializationCtor;
75 internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
77 bool bNeedSecurityCheck = true;
78 bool bCanBeCached = false;
79 bool bSecurityCheckOff = false;
82 CreateInstanceCheckThis();
85 bSecurityCheckOff = true;
87 return CreateInstanceMono (!publicOnly);
90 object CreateInstanceMono (bool nonPublic)
92 var ctor = GetDefaultConstructor ();
93 if (!nonPublic && ctor != null && !ctor.IsPublic) {
98 Type elementType = this.GetRootElementType();
99 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
100 throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
103 return CreateInstanceInternal (this);
105 throw new MissingMethodException (Locale.GetText ("Default constructor not found for type " + FullName));
108 // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
110 throw new MissingMethodException (Locale.GetText ("Cannot create an abstract class '{0}'.", FullName));
113 return ctor.InternalInvoke (null, null);
116 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
119 var res = TryConvertToType (value, ref failed);
123 if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
124 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
126 if (binder != null && binder != Type.DefaultBinder)
127 return binder.ChangeType (value, this, culture);
129 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
132 object TryConvertToType (object value, ref bool failed)
134 if (IsInstanceOfType (value)) {
139 var elementType = GetElementType ();
140 if (value == null || elementType.IsInstanceOfType (value)) {
149 var type = Enum.GetUnderlyingType (this);
150 if (type == value.GetType ())
152 var res = IsConvertibleToPrimitiveType (value, this);
155 } else if (IsPrimitive) {
156 var res = IsConvertibleToPrimitiveType (value, this);
159 } else if (IsPointer) {
160 var vtype = value.GetType ();
161 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
169 // Binder uses some incompatible conversion rules. For example
170 // int value cannot be used with decimal parameter but in other
171 // ways it's more flexible than normal convertor, for example
172 // long value can be used with int based enum
173 static object IsConvertibleToPrimitiveType (object value, Type targetType)
175 var type = value.GetType ();
177 type = Enum.GetUnderlyingType (type);
178 if (type == targetType)
182 var from = Type.GetTypeCode (type);
183 var to = Type.GetTypeCode (targetType);
189 return (Char) (Byte) value;
190 case TypeCode.UInt16:
197 return (Int16) (Byte) value;
199 return (Int16) (SByte) value;
202 case TypeCode.UInt16:
205 return (UInt16) (Byte) value;
213 return (Int32) (Byte) value;
215 return (Int32) (SByte) value;
217 return (Int32) (Char) value;
219 return (Int32) (Int16) value;
220 case TypeCode.UInt16:
221 return (Int32) (UInt16) value;
224 case TypeCode.UInt32:
227 return (UInt32) (Byte) value;
229 return (UInt32) (Char) value;
230 case TypeCode.UInt16:
231 return (UInt32) (UInt16) value;
237 return (Int64) (Byte) value;
239 return (Int64) (SByte) value;
241 return (Int64) (Int16) value;
243 return (Int64) (Char) value;
244 case TypeCode.UInt16:
245 return (Int64) (UInt16) value;
247 return (Int64) (Int32) value;
248 case TypeCode.UInt32:
249 return (Int64) (UInt32) value;
252 case TypeCode.UInt64:
255 return (UInt64) (Byte) value;
257 return (UInt64) (Char) value;
258 case TypeCode.UInt16:
259 return (UInt64) (UInt16) value;
260 case TypeCode.UInt32:
261 return (UInt64) (UInt32) value;
264 case TypeCode.Single:
267 return (Single) (Byte) value;
269 return (Single) (SByte) value;
271 return (Single) (Int16) value;
273 return (Single) (Char) value;
274 case TypeCode.UInt16:
275 return (Single) (UInt16) value;
277 return (Single) (Int32) value;
278 case TypeCode.UInt32:
279 return (Single) (UInt32) value;
281 return (Single) (Int64) value;
282 case TypeCode.UInt64:
283 return (Single) (UInt64) value;
286 case TypeCode.Double:
289 return (Double) (Byte) value;
291 return (Double) (SByte) value;
293 return (Double) (Char) value;
295 return (Double) (Int16) value;
296 case TypeCode.UInt16:
297 return (Double) (UInt16) value;
299 return (Double) (Int32) value;
300 case TypeCode.UInt32:
301 return (Double) (UInt32) value;
303 return (Double) (Int64) value;
304 case TypeCode.UInt64:
305 return (Double) (UInt64) value;
306 case TypeCode.Single:
307 return (Double) (Single) value;
312 // Everything else is rejected
316 string GetCachedName (TypeNameKind kind)
319 case TypeNameKind.SerializationName:
322 throw new NotImplementedException ();
326 [MethodImplAttribute(MethodImplOptions.InternalCall)]
327 extern Type make_array_type (int rank);
329 public override Type MakeArrayType ()
331 return make_array_type (0);
334 public override Type MakeArrayType (int rank)
336 if (rank < 1 || rank > 255)
337 throw new IndexOutOfRangeException ();
338 return make_array_type (rank);
341 [MethodImplAttribute(MethodImplOptions.InternalCall)]
342 extern Type make_byref_type ();
344 public override Type MakeByRefType ()
347 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
348 return make_byref_type ();
351 [MethodImplAttribute(MethodImplOptions.InternalCall)]
352 static extern Type MakePointerType (Type type);
354 public override Type MakePointerType ()
356 return MakePointerType (this);
359 public override StructLayoutAttribute StructLayoutAttribute {
361 return GetStructLayoutAttribute ();
365 public override bool ContainsGenericParameters {
367 if (IsGenericParameter)
371 foreach (Type arg in GetGenericArguments ())
372 if (arg.ContainsGenericParameters)
377 return GetElementType ().ContainsGenericParameters;
383 public override Type[] GetGenericParameterConstraints()
385 if (!IsGenericParameter)
386 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
387 Contract.EndContractBlock();
389 Type[] constraints = GetGenericParameterConstraints_impl ();
391 if (constraints == null)
392 constraints = EmptyArray<Type>.Value;
397 internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
399 var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
400 var ctor = gt.GetDefaultConstructor ();
401 return ctor.InternalInvoke (null, null);
404 [MethodImplAttribute(MethodImplOptions.InternalCall)]
405 static extern Type MakeGenericType (Type gt, Type [] types);
407 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
410 [MethodImplAttribute(MethodImplOptions.InternalCall)]
411 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
413 [MethodImplAttribute(MethodImplOptions.InternalCall)]
414 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
416 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
418 if (IsGenericParameter)
419 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
421 if ((object)ifaceType == null)
422 throw new ArgumentNullException("ifaceType");
423 Contract.EndContractBlock();
425 RuntimeType ifaceRtType = ifaceType as RuntimeType;
427 if (ifaceRtType == null)
428 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
430 InterfaceMapping res;
431 if (!ifaceType.IsInterface)
432 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
434 throw new ArgumentException ("'this' type cannot be an interface itself");
435 res.TargetType = this;
436 res.InterfaceType = ifaceType;
437 GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
438 if (res.TargetMethods == null)
439 throw new ArgumentException (Locale.GetText ("Interface not found"), "ifaceType");
444 [MethodImplAttribute(MethodImplOptions.InternalCall)]
445 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
447 public override Guid GUID {
449 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
452 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
456 StructLayoutAttribute GetStructLayoutAttribute ()
460 if (IsLayoutSequential)
461 kind = LayoutKind.Sequential;
462 else if (IsExplicitLayout)
463 kind = LayoutKind.Explicit;
465 kind = LayoutKind.Auto;
467 StructLayoutAttribute attr = new StructLayoutAttribute (kind);
470 attr.CharSet = CharSet.Unicode;
471 else if (IsAnsiClass)
472 attr.CharSet = CharSet.Ansi;
474 attr.CharSet = CharSet.Auto;
476 if (kind != LayoutKind.Auto) {
478 GetPacking (out packing, out attr.Size);
479 // 0 means no data provided, we end up with default value
487 [MethodImplAttribute(MethodImplOptions.InternalCall)]
488 extern void GetPacking (out int packing, out int size);
491 private static Dictionary<Guid, Type> clsid_types;
492 private static AssemblyBuilder clsid_assemblybuilder;
495 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
500 if (clsid_types == null)
502 Dictionary<Guid, Type> new_clsid_types = new Dictionary<Guid, Type> ();
503 Interlocked.CompareExchange<Dictionary<Guid, Type>>(
504 ref clsid_types, new_clsid_types, null);
508 if (clsid_types.TryGetValue(clsid, out result))
511 if (clsid_assemblybuilder == null)
513 AssemblyName assemblyname = new AssemblyName ();
514 assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
515 clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
516 assemblyname, AssemblyBuilderAccess.Run);
518 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
521 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
522 TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
524 Type[] guidattrtypes = new Type[] { typeof(string) };
526 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
527 typeof(GuidAttribute).GetConstructor (guidattrtypes),
528 new object[] { clsid.ToString () });
530 typebuilder.SetCustomAttribute (customattr);
532 customattr = new CustomAttributeBuilder (
533 typeof(ComImportAttribute).GetConstructor (EmptyTypes),
536 typebuilder.SetCustomAttribute (customattr);
538 result = typebuilder.CreateType ();
540 clsid_types.Add(clsid, result);
545 throw new NotImplementedException ("Unmanaged activation removed");
549 protected override TypeCode GetTypeCodeImpl ()
551 return GetTypeCodeImplInternal (this);
554 [MethodImplAttribute(MethodImplOptions.InternalCall)]
555 extern static TypeCode GetTypeCodeImplInternal (Type type);
557 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
559 throw new NotImplementedException ("Unmanaged activation is not supported");
562 public override string ToString()
564 return getFullName (false, false);
567 bool IsGenericCOMObjectImpl ()
572 [MethodImplAttribute (MethodImplOptions.InternalCall)]
573 static extern object CreateInstanceInternal (Type type);
575 public extern override MethodBase DeclaringMethod {
576 [MethodImplAttribute(MethodImplOptions.InternalCall)]
580 [MethodImplAttribute(MethodImplOptions.InternalCall)]
581 internal extern string getFullName(bool full_name, bool assembly_qualified);
583 [MethodImplAttribute(MethodImplOptions.InternalCall)]
584 extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
586 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587 extern GenericParameterAttributes GetGenericParameterAttributes ();
589 [MethodImplAttribute(MethodImplOptions.InternalCall)]
590 extern Type[] GetGenericParameterConstraints_impl ();
592 [MethodImplAttribute(MethodImplOptions.InternalCall)]
593 extern int GetGenericParameterPosition ();
595 [MethodImplAttribute(MethodImplOptions.InternalCall)]
596 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
598 [MethodImplAttribute(MethodImplOptions.InternalCall)]
599 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
601 [MethodImplAttribute(MethodImplOptions.InternalCall)]
602 public extern override Type[] GetInterfaces();
604 [MethodImplAttribute(MethodImplOptions.InternalCall)]
605 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);
607 public override string AssemblyQualifiedName {
609 return getFullName (true, true);
613 public extern override Type DeclaringType {
614 [MethodImplAttribute(MethodImplOptions.InternalCall)]
618 public override string FullName {
620 throw new NotImplementedException ();
624 public extern override string Name {
625 [MethodImplAttribute(MethodImplOptions.InternalCall)]
629 public extern override string Namespace {
630 [MethodImplAttribute(MethodImplOptions.InternalCall)]
634 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
635 [MethodImplAttribute(MethodImplOptions.InternalCall)]
636 public extern int get_core_clr_security_level ();
638 public override bool IsSecurityTransparent {
639 get { return get_core_clr_security_level () == 0; }
642 public override bool IsSecurityCritical {
643 get { return get_core_clr_security_level () > 0; }
646 public override bool IsSecuritySafeCritical {
647 get { return get_core_clr_security_level () == 1; }