5 // Sean MacIsaac (macisaac@ximian.com)
6 // Paolo Molaro (lupus@ximian.com)
7 // Patrik Torstensson (patrik.torstensson@labs2.com)
8 // Gonzalo Paniagua (gonzalo@ximian.com)
9 // Marek Safar (marek.safar@gmail.com)
11 // (c) 2001-2003 Ximian, Inc.
12 // Copyright (C) 2003-2005 Novell, Inc (http://www.novell.com)
13 // Copyright (C) 2013 Xamarin Inc (http://www.xamarin.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections.Generic;
36 using System.Globalization;
37 using System.Reflection;
38 using System.Runtime.InteropServices;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.Serialization;
41 using System.Security;
45 // Contains information about the type which is expensive to compute
46 [StructLayout (LayoutKind.Sequential)]
47 internal class MonoTypeInfo {
48 public string full_name;
49 public MonoCMethod default_ctor;
53 [StructLayout (LayoutKind.Sequential)]
54 sealed class MonoType :
63 MonoTypeInfo type_info;
65 [MethodImplAttribute(MethodImplOptions.InternalCall)]
66 private static extern void type_from_obj (MonoType type, Object obj);
68 internal MonoType (Object obj)
70 // this should not be used - lupus
71 type_from_obj (this, obj);
73 throw new NotImplementedException ();
76 [MethodImplAttribute(MethodImplOptions.InternalCall)]
77 private static extern TypeAttributes get_attributes (Type type);
79 public MonoCMethod GetDefaultConstructor ()
81 MonoCMethod ctor = null;
83 if (type_info == null)
84 type_info = new MonoTypeInfo ();
86 ctor = type_info.default_ctor;
89 var ctors = GetConstructors (BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
91 for (int i = 0; i < ctors.Length; ++i) {
92 if (ctors [i].GetParametersCount () == 0) {
93 type_info.default_ctor = ctor = (MonoCMethod) ctors [i];
102 protected override TypeAttributes GetAttributeFlagsImpl ()
104 return get_attributes (this);
107 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
109 CallingConventions callConvention,
111 ParameterModifier[] modifiers)
113 ConstructorInfo[] methods = GetConstructors (bindingAttr);
114 return GetConstructorImpl (methods, bindingAttr, binder, callConvention, types, modifiers);
117 internal static ConstructorInfo GetConstructorImpl (ConstructorInfo[] methods, BindingFlags bindingAttr,
119 CallingConventions callConvention,
121 ParameterModifier[] modifiers)
123 if (bindingAttr == BindingFlags.Default)
124 bindingAttr = BindingFlags.Public | BindingFlags.Instance;
126 ConstructorInfo found = null;
129 foreach (ConstructorInfo m in methods) {
130 // Under MS.NET, Standard|HasThis matches Standard...
131 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
140 throw new AmbiguousMatchException ();
141 return (ConstructorInfo) CheckMethodSecurity (found);
143 match = new MethodBase [count];
148 foreach (ConstructorInfo m in methods) {
149 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
155 binder = Binder.DefaultBinder;
156 return (ConstructorInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
159 [MethodImplAttribute(MethodImplOptions.InternalCall)]
160 internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
162 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
164 return GetConstructors_internal (bindingAttr, this);
167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168 extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
170 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
173 throw new ArgumentNullException ("name");
175 return InternalGetEvent (name, bindingAttr);
178 [MethodImplAttribute(MethodImplOptions.InternalCall)]
179 internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
181 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
183 return GetEvents_internal (bindingAttr, this);
186 [MethodImplAttribute(MethodImplOptions.InternalCall)]
187 public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
189 [MethodImplAttribute(MethodImplOptions.InternalCall)]
190 internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
192 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
194 return GetFields_internal (bindingAttr, this);
197 public override Type GetInterface (string name, bool ignoreCase)
200 throw new ArgumentNullException ();
202 Type[] interfaces = GetInterfaces();
204 foreach (Type type in interfaces) {
205 /*We must compare against the generic type definition*/
206 Type t = type.IsGenericType ? type.GetGenericTypeDefinition () : type;
208 if (String.Compare (t.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
210 if (String.Compare (t.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
217 [MethodImplAttribute(MethodImplOptions.InternalCall)]
218 public extern override Type[] GetInterfaces();
220 public override MemberInfo[] GetMembers( BindingFlags bindingAttr)
222 return FindMembers (MemberTypes.All, bindingAttr, null, null);
225 [MethodImplAttribute(MethodImplOptions.InternalCall)]
226 internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
228 public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
230 return GetMethodsByName (null, bindingAttr, false, this);
233 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
235 CallingConventions callConvention,
236 Type[] types, ParameterModifier[] modifiers)
238 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
239 MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
240 MethodInfo found = null;
244 foreach (MethodInfo m in methods) {
245 // Under MS.NET, Standard|HasThis matches Standard...
246 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
255 if (count == 1 && types == null)
256 return (MethodInfo) CheckMethodSecurity (found);
258 match = new MethodBase [count];
263 foreach (MethodInfo m in methods) {
264 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
271 return (MethodInfo) CheckMethodSecurity (Binder.FindMostDerivedMatch (match));
274 binder = Binder.DefaultBinder;
276 return (MethodInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
279 [MethodImplAttribute(MethodImplOptions.InternalCall)]
280 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
282 [MethodImplAttribute(MethodImplOptions.InternalCall)]
283 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
285 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
287 if (fromNoninstanciated == null)
288 throw new ArgumentNullException ("fromNoninstanciated");
289 return GetCorrespondingInflatedMethod (fromNoninstanciated);
292 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
294 if (fromNoninstanciated == null)
295 throw new ArgumentNullException ("fromNoninstanciated");
296 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
299 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
301 /* create sensible flags from given FieldInfo */
302 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
303 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
304 return GetField (fromNoninstanciated.Name, flags);
307 [MethodImplAttribute(MethodImplOptions.InternalCall)]
308 public extern override Type GetNestedType (string name, BindingFlags bindingAttr);
310 [MethodImplAttribute(MethodImplOptions.InternalCall)]
311 public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
313 [MethodImplAttribute(MethodImplOptions.InternalCall)]
314 internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
316 public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
318 return GetPropertiesByName (null, bindingAttr, false, this);
321 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
322 Binder binder, Type returnType,
324 ParameterModifier[] modifiers)
326 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
327 PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
328 int count = props.Length;
332 if (count == 1 && (types == null || types.Length == 0) &&
333 (returnType == null || returnType == props[0].PropertyType))
337 binder = Binder.DefaultBinder;
339 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
342 protected override bool HasElementTypeImpl ()
344 return IsArrayImpl() || IsByRefImpl() || IsPointerImpl ();
347 protected override bool IsArrayImpl ()
349 return Type.IsArrayImpl (this);
352 [MethodImplAttribute(MethodImplOptions.InternalCall)]
353 protected extern override bool IsByRefImpl ();
355 [MethodImplAttribute (MethodImplOptions.InternalCall)]
356 protected extern override bool IsCOMObjectImpl ();
358 [MethodImplAttribute(MethodImplOptions.InternalCall)]
359 protected extern override bool IsPointerImpl ();
361 [MethodImplAttribute(MethodImplOptions.InternalCall)]
362 protected extern override bool IsPrimitiveImpl ();
364 public override bool IsSubclassOf (Type type)
367 throw new ArgumentNullException ("type");
369 return base.IsSubclassOf (type);
372 public override object InvokeMember (string name, BindingFlags invokeAttr,
373 Binder binder, object target, object[] args,
374 ParameterModifier[] modifiers,
375 CultureInfo culture, string[] namedParameters)
377 const string bindingflags_arg = "bindingFlags";
380 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
381 if ((invokeAttr & (BindingFlags.GetField |
382 BindingFlags.GetField | BindingFlags.GetProperty |
383 BindingFlags.SetProperty)) != 0)
384 throw new ArgumentException (bindingflags_arg);
385 } else if (name == null)
386 throw new ArgumentNullException ("name");
387 if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
388 throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg);
389 if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
390 throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg);
391 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
392 if ((invokeAttr & BindingFlags.SetField) != 0)
393 throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg);
394 if ((invokeAttr & BindingFlags.SetProperty) != 0)
395 throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg);
397 if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
398 throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
399 if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0)
400 throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg);
402 /* set some defaults if none are provided :-( */
403 if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
404 invokeAttr |= BindingFlags.Public;
405 if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0)
406 invokeAttr |= BindingFlags.Static|BindingFlags.Instance;
409 binder = DefaultBinder;
411 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
412 return Activator.CreateInstance (this, invokeAttr, binder, args, culture);
414 if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) {
415 DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute));
416 name = attr.MemberName;
418 bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
419 string throwMissingMethodDescription = null;
420 bool throwMissingFieldException = false;
422 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
423 MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
426 args = EmptyArray<object>.Value;
427 MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
429 if (methods.Length > 0)
430 throwMissingMethodDescription = "The best match for method " + name + " has some invalid parameter.";
432 throwMissingMethodDescription = "Cannot find method " + name + ".";
434 ParameterInfo[] parameters = m.GetParametersInternal();
435 for (int i = 0; i < parameters.Length; ++i) {
436 if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault)
437 throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters");
439 object result = m.Invoke (target, invokeAttr, binder, args, culture);
440 binder.ReorderArgumentArray (ref args, state);
444 if ((invokeAttr & BindingFlags.GetField) != 0) {
445 FieldInfo f = GetField (name, invokeAttr);
447 return f.GetValue (target);
448 } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
449 throwMissingFieldException = true;
451 /* try GetProperty */
452 } else if ((invokeAttr & BindingFlags.SetField) != 0) {
453 FieldInfo f = GetField (name, invokeAttr);
456 throw new ArgumentNullException ("providedArgs");
457 if ((args == null) || args.Length != 1)
458 throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg);
459 f.SetValue (target, args [0]);
461 } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
462 throwMissingFieldException = true;
464 /* try SetProperty */
466 if ((invokeAttr & BindingFlags.GetProperty) != 0) {
467 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
470 for (i = 0; i < properties.Length; ++i) {
471 if ((properties [i].GetGetMethod (true) != null))
474 MethodBase[] smethods = new MethodBase [count];
476 for (i = 0; i < properties.Length; ++i) {
477 MethodBase mb = properties [i].GetGetMethod (true);
479 smethods [count++] = mb;
481 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
483 throwMissingFieldException = true;
485 object result = m.Invoke (target, invokeAttr, binder, args, culture);
486 binder.ReorderArgumentArray (ref args, state);
489 } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
490 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
493 for (i = 0; i < properties.Length; ++i) {
494 if (properties [i].GetSetMethod (true) != null)
497 MethodBase[] smethods = new MethodBase [count];
499 for (i = 0; i < properties.Length; ++i) {
500 MethodBase mb = properties [i].GetSetMethod (true);
502 smethods [count++] = mb;
504 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
506 throwMissingFieldException = true;
508 object result = m.Invoke (target, invokeAttr, binder, args, culture);
509 binder.ReorderArgumentArray (ref args, state);
513 if (throwMissingMethodDescription != null)
514 throw new MissingMethodException(throwMissingMethodDescription);
515 if (throwMissingFieldException)
516 throw new MissingFieldException("Cannot find variable " + name + ".");
521 [MethodImplAttribute(MethodImplOptions.InternalCall)]
522 public extern override Type GetElementType ();
524 public override Type UnderlyingSystemType {
526 // This has _nothing_ to do with getting the base type of an enum etc.
531 public extern override Assembly Assembly {
532 [MethodImplAttribute(MethodImplOptions.InternalCall)]
536 public override string AssemblyQualifiedName {
538 return getFullName (true, true);
542 [MethodImplAttribute(MethodImplOptions.InternalCall)]
543 private extern string getFullName(bool full_name, bool assembly_qualified);
545 public extern override Type BaseType {
546 [MethodImplAttribute(MethodImplOptions.InternalCall)]
550 public override string FullName {
553 // This doesn't need locking
554 if (type_info == null)
555 type_info = new MonoTypeInfo ();
556 if ((fullName = type_info.full_name) == null)
557 fullName = type_info.full_name = getFullName (true, false);
563 public override Guid GUID {
565 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
568 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
572 public override bool IsDefined (Type attributeType, bool inherit)
574 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
577 public override object[] GetCustomAttributes (bool inherit)
579 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
582 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
584 if (attributeType == null)
586 throw new ArgumentNullException("attributeType");
589 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
592 public override MemberTypes MemberType {
594 if (DeclaringType != null && !IsGenericParameter)
595 return MemberTypes.NestedType;
597 return MemberTypes.TypeInfo;
601 public extern override string Name {
602 [MethodImplAttribute(MethodImplOptions.InternalCall)]
606 public extern override string Namespace {
607 [MethodImplAttribute(MethodImplOptions.InternalCall)]
611 public extern override Module Module {
612 [MethodImplAttribute(MethodImplOptions.InternalCall)]
616 public extern override Type DeclaringType {
617 [MethodImplAttribute(MethodImplOptions.InternalCall)]
621 public override Type ReflectedType {
623 return DeclaringType;
627 public override RuntimeTypeHandle TypeHandle {
633 [MethodImplAttribute(MethodImplOptions.InternalCall)]
634 public extern override int GetArrayRank ();
636 public void GetObjectData(SerializationInfo info, StreamingContext context)
638 UnitySerializationHolder.GetTypeData (this, info, context);
641 public override string ToString()
643 return getFullName (false, false);
646 [MethodImplAttribute(MethodImplOptions.InternalCall)]
647 public extern override Type [] GetGenericArguments ();
649 public override bool ContainsGenericParameters {
651 if (IsGenericParameter)
655 foreach (Type arg in GetGenericArguments ())
656 if (arg.ContainsGenericParameters)
661 return GetElementType ().ContainsGenericParameters;
667 public extern override bool IsGenericParameter {
668 [MethodImplAttribute(MethodImplOptions.InternalCall)]
672 public extern override MethodBase DeclaringMethod {
673 [MethodImplAttribute(MethodImplOptions.InternalCall)]
677 public override Type GetGenericTypeDefinition () {
678 Type res = GetGenericTypeDefinition_impl ();
680 throw new InvalidOperationException ();
686 public override IList<CustomAttributeData> GetCustomAttributesData () {
687 return CustomAttributeData.GetCustomAttributes (this);
691 public override Array GetEnumValues () {
693 throw new ArgumentException ("Type is not an enumeration", "enumType");
695 return Enum.GetValues (this);
699 static MethodBase CheckMethodSecurity (MethodBase mb)
704 if (!SecurityManager.SecurityEnabled || (mb == null))
707 // Sadly we have no way to know which kind of security action this is
708 // so we must do it the hard way. Actually this isn't so bad
709 // because we can skip the (mb.Attributes & MethodAttributes.HasSecurity)
710 // icall required (and do it ourselves)
712 // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
713 return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
718 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
719 [MethodImplAttribute(MethodImplOptions.InternalCall)]
720 public extern int get_core_clr_security_level ();
722 public override bool IsSecurityTransparent
724 get { return get_core_clr_security_level () == 0; }
727 public override bool IsSecurityCritical
729 get { return get_core_clr_security_level () > 0; }
732 public override bool IsSecuritySafeCritical
734 get { return get_core_clr_security_level () == 1; }
737 public override StructLayoutAttribute StructLayoutAttribute {
739 return GetStructLayoutAttribute ();
744 internal override bool IsUserType {
751 public override bool IsConstructedGenericType {
753 return IsGenericType && !ContainsGenericParameters;