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)
10 // (c) 2001-2003 Ximian, Inc.
11 // Copyright (C) 2003-2005 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections.Generic;
34 using System.Globalization;
35 using System.Reflection;
36 using System.Runtime.InteropServices;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.Serialization;
39 using System.Security;
43 // Contains information about the type which is expensive to compute
44 [StructLayout (LayoutKind.Sequential)]
45 internal class MonoTypeInfo {
46 public string full_name;
47 public ConstructorInfo default_ctor;
51 [StructLayout (LayoutKind.Sequential)]
52 internal class MonoType : Type, ISerializable
55 MonoTypeInfo type_info;
57 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58 private static extern void type_from_obj (MonoType type, Object obj);
60 internal MonoType (Object obj)
62 // this should not be used - lupus
63 type_from_obj (this, obj);
65 throw new NotImplementedException ();
68 [MethodImplAttribute(MethodImplOptions.InternalCall)]
69 private static extern TypeAttributes get_attributes (Type type);
71 internal ConstructorInfo GetDefaultConstructor () {
72 ConstructorInfo ctor = null;
74 if (type_info == null)
75 type_info = new MonoTypeInfo ();
76 if ((ctor = type_info.default_ctor) == null) {
77 const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;
79 ctor = type_info.default_ctor = GetConstructor (flags, null, CallingConventions.Any, Type.EmptyTypes, null);
85 protected override TypeAttributes GetAttributeFlagsImpl ()
87 return get_attributes (this);
90 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
92 CallingConventions callConvention,
94 ParameterModifier[] modifiers)
96 ConstructorInfo[] methods = GetConstructors (bindingAttr);
97 return GetConstructorImpl (methods, bindingAttr, binder, callConvention, types, modifiers);
100 internal static ConstructorInfo GetConstructorImpl (ConstructorInfo[] methods, BindingFlags bindingAttr,
102 CallingConventions callConvention,
104 ParameterModifier[] modifiers)
106 if (bindingAttr == BindingFlags.Default)
107 bindingAttr = BindingFlags.Public | BindingFlags.Instance;
109 ConstructorInfo found = null;
112 foreach (ConstructorInfo m in methods) {
113 // Under MS.NET, Standard|HasThis matches Standard...
114 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
123 throw new AmbiguousMatchException ();
124 return (ConstructorInfo) CheckMethodSecurity (found);
126 match = new MethodBase [count];
131 foreach (ConstructorInfo m in methods) {
132 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
138 binder = Binder.DefaultBinder;
139 return (ConstructorInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
142 [MethodImplAttribute(MethodImplOptions.InternalCall)]
143 internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
145 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
147 return GetConstructors_internal (bindingAttr, this);
150 [MethodImplAttribute(MethodImplOptions.InternalCall)]
151 extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
153 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
156 throw new ArgumentNullException ("name");
158 return InternalGetEvent (name, bindingAttr);
161 [MethodImplAttribute(MethodImplOptions.InternalCall)]
162 internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
164 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
166 return GetEvents_internal (bindingAttr, this);
169 [MethodImplAttribute(MethodImplOptions.InternalCall)]
170 public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
172 [MethodImplAttribute(MethodImplOptions.InternalCall)]
173 internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
175 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
177 return GetFields_internal (bindingAttr, this);
180 public override Type GetInterface (string name, bool ignoreCase)
183 throw new ArgumentNullException ();
185 Type[] interfaces = GetInterfaces();
187 foreach (Type type in interfaces) {
188 /*We must compare against the generic type definition*/
189 Type t = type.IsGenericType ? type.GetGenericTypeDefinition () : type;
191 if (String.Compare (t.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
193 if (String.Compare (t.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
200 [MethodImplAttribute(MethodImplOptions.InternalCall)]
201 public extern override Type[] GetInterfaces();
203 public override MemberInfo[] GetMembers( BindingFlags bindingAttr)
205 return FindMembers (MemberTypes.All, bindingAttr, null, null);
208 [MethodImplAttribute(MethodImplOptions.InternalCall)]
209 internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
211 public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
213 return GetMethodsByName (null, bindingAttr, false, this);
216 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
218 CallingConventions callConvention,
219 Type[] types, ParameterModifier[] modifiers)
221 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
222 MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
223 MethodInfo found = null;
227 foreach (MethodInfo m in methods) {
228 // Under MS.NET, Standard|HasThis matches Standard...
229 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
238 if (count == 1 && types == null)
239 return (MethodInfo) CheckMethodSecurity (found);
241 match = new MethodBase [count];
246 foreach (MethodInfo m in methods) {
247 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
254 return (MethodInfo) CheckMethodSecurity (Binder.FindMostDerivedMatch (match));
257 binder = Binder.DefaultBinder;
259 return (MethodInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
262 [MethodImplAttribute(MethodImplOptions.InternalCall)]
263 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
265 [MethodImplAttribute(MethodImplOptions.InternalCall)]
266 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
268 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
270 if (fromNoninstanciated == null)
271 throw new ArgumentNullException ("fromNoninstanciated");
272 return GetCorrespondingInflatedMethod (fromNoninstanciated);
275 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
277 if (fromNoninstanciated == null)
278 throw new ArgumentNullException ("fromNoninstanciated");
279 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
282 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
284 /* create sensible flags from given FieldInfo */
285 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
286 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
287 return GetField (fromNoninstanciated.Name, flags);
290 [MethodImplAttribute(MethodImplOptions.InternalCall)]
291 public extern override Type GetNestedType (string name, BindingFlags bindingAttr);
293 [MethodImplAttribute(MethodImplOptions.InternalCall)]
294 public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
296 [MethodImplAttribute(MethodImplOptions.InternalCall)]
297 internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
299 public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
301 return GetPropertiesByName (null, bindingAttr, false, this);
304 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
305 Binder binder, Type returnType,
307 ParameterModifier[] modifiers)
309 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
310 PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
311 int count = props.Length;
315 if (count == 1 && (types == null || types.Length == 0) &&
316 (returnType == null || returnType == props[0].PropertyType))
320 binder = Binder.DefaultBinder;
322 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
325 protected override bool HasElementTypeImpl ()
327 return IsArrayImpl() || IsByRefImpl() || IsPointerImpl ();
330 protected override bool IsArrayImpl ()
332 return Type.IsArrayImpl (this);
335 [MethodImplAttribute(MethodImplOptions.InternalCall)]
336 protected extern override bool IsByRefImpl ();
338 [MethodImplAttribute (MethodImplOptions.InternalCall)]
339 protected extern override bool IsCOMObjectImpl ();
341 [MethodImplAttribute(MethodImplOptions.InternalCall)]
342 protected extern override bool IsPointerImpl ();
344 [MethodImplAttribute(MethodImplOptions.InternalCall)]
345 protected extern override bool IsPrimitiveImpl ();
347 public override bool IsSubclassOf (Type type)
350 throw new ArgumentNullException ("type");
352 return base.IsSubclassOf (type);
355 public override object InvokeMember (string name, BindingFlags invokeAttr,
356 Binder binder, object target, object[] args,
357 ParameterModifier[] modifiers,
358 CultureInfo culture, string[] namedParameters)
360 const string bindingflags_arg = "bindingFlags";
363 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
364 if ((invokeAttr & (BindingFlags.GetField |
365 BindingFlags.GetField | BindingFlags.GetProperty |
366 BindingFlags.SetProperty)) != 0)
367 throw new ArgumentException (bindingflags_arg);
368 } else if (name == null)
369 throw new ArgumentNullException ("name");
370 if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
371 throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg);
372 if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
373 throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg);
374 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
375 if ((invokeAttr & BindingFlags.SetField) != 0)
376 throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg);
377 if ((invokeAttr & BindingFlags.SetProperty) != 0)
378 throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg);
380 if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
381 throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
382 if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0)
383 throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg);
385 /* set some defaults if none are provided :-( */
386 if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
387 invokeAttr |= BindingFlags.Public;
388 if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0)
389 invokeAttr |= BindingFlags.Static|BindingFlags.Instance;
392 binder = Binder.DefaultBinder;
393 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
394 /* the name is ignored */
395 invokeAttr |= BindingFlags.DeclaredOnly;
396 ConstructorInfo[] ctors = GetConstructors (invokeAttr);
398 MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state);
400 if (this.IsValueType && args == null)
401 return Activator.CreateInstanceInternal (this);
403 throw new MissingMethodException ("Constructor on type '" + FullName + "' not found.");
405 object result = ctor.Invoke (target, invokeAttr, binder, args, culture);
406 binder.ReorderArgumentArray (ref args, state);
409 if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) {
410 DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute));
411 name = attr.MemberName;
413 bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
414 string throwMissingMethodDescription = null;
415 bool throwMissingFieldException = false;
417 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
418 MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
421 args = new object [0];
422 MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
424 if (methods.Length > 0)
425 throwMissingMethodDescription = "The best match for method " + name + " has some invalid parameter.";
427 throwMissingMethodDescription = "Cannot find method " + name + ".";
429 ParameterInfo[] parameters = m.GetParameters();
430 for (int i = 0; i < parameters.Length; ++i) {
431 if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault)
432 throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters");
434 object result = m.Invoke (target, invokeAttr, binder, args, culture);
435 binder.ReorderArgumentArray (ref args, state);
439 if ((invokeAttr & BindingFlags.GetField) != 0) {
440 FieldInfo f = GetField (name, invokeAttr);
442 return f.GetValue (target);
443 } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
444 throwMissingFieldException = true;
446 /* try GetProperty */
447 } else if ((invokeAttr & BindingFlags.SetField) != 0) {
448 FieldInfo f = GetField (name, invokeAttr);
451 throw new ArgumentNullException ("providedArgs");
452 if ((args == null) || args.Length != 1)
453 throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg);
454 f.SetValue (target, args [0]);
456 } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
457 throwMissingFieldException = true;
459 /* try SetProperty */
461 if ((invokeAttr & BindingFlags.GetProperty) != 0) {
462 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
465 for (i = 0; i < properties.Length; ++i) {
466 if ((properties [i].GetGetMethod (true) != null))
469 MethodBase[] smethods = new MethodBase [count];
471 for (i = 0; i < properties.Length; ++i) {
472 MethodBase mb = properties [i].GetGetMethod (true);
474 smethods [count++] = mb;
476 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
478 throwMissingFieldException = true;
480 object result = m.Invoke (target, invokeAttr, binder, args, culture);
481 binder.ReorderArgumentArray (ref args, state);
484 } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
485 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
488 for (i = 0; i < properties.Length; ++i) {
489 if (properties [i].GetSetMethod (true) != null)
492 MethodBase[] smethods = new MethodBase [count];
494 for (i = 0; i < properties.Length; ++i) {
495 MethodBase mb = properties [i].GetSetMethod (true);
497 smethods [count++] = mb;
499 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
501 throwMissingFieldException = true;
503 object result = m.Invoke (target, invokeAttr, binder, args, culture);
504 binder.ReorderArgumentArray (ref args, state);
508 if (throwMissingMethodDescription != null)
509 throw new MissingMethodException(throwMissingMethodDescription);
510 if (throwMissingFieldException)
511 throw new MissingFieldException("Cannot find variable " + name + ".");
516 [MethodImplAttribute(MethodImplOptions.InternalCall)]
517 public extern override Type GetElementType ();
519 public override Type UnderlyingSystemType {
521 // This has _nothing_ to do with getting the base type of an enum etc.
526 public extern override Assembly Assembly {
527 [MethodImplAttribute(MethodImplOptions.InternalCall)]
531 public override string AssemblyQualifiedName {
533 return getFullName (true, true);
537 [MethodImplAttribute(MethodImplOptions.InternalCall)]
538 private extern string getFullName(bool full_name, bool assembly_qualified);
540 public extern override Type BaseType {
541 [MethodImplAttribute(MethodImplOptions.InternalCall)]
545 public override string FullName {
548 // This doesn't need locking
549 if (type_info == null)
550 type_info = new MonoTypeInfo ();
551 if ((fullName = type_info.full_name) == null)
552 fullName = type_info.full_name = getFullName (true, false);
558 public override Guid GUID {
560 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
563 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
567 public override bool IsDefined (Type attributeType, bool inherit)
569 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
572 public override object[] GetCustomAttributes (bool inherit)
574 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
577 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
579 if (attributeType == null)
581 throw new ArgumentNullException("attributeType");
584 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
587 public override MemberTypes MemberType {
589 if (DeclaringType != null && !IsGenericParameter)
590 return MemberTypes.NestedType;
592 return MemberTypes.TypeInfo;
596 public extern override string Name {
597 [MethodImplAttribute(MethodImplOptions.InternalCall)]
601 public extern override string Namespace {
602 [MethodImplAttribute(MethodImplOptions.InternalCall)]
606 public extern override Module Module {
607 [MethodImplAttribute(MethodImplOptions.InternalCall)]
611 public extern override Type DeclaringType {
612 [MethodImplAttribute(MethodImplOptions.InternalCall)]
616 public override Type ReflectedType {
618 return DeclaringType;
622 public override RuntimeTypeHandle TypeHandle {
628 [MethodImplAttribute(MethodImplOptions.InternalCall)]
629 public extern override int GetArrayRank ();
631 public void GetObjectData(SerializationInfo info, StreamingContext context)
633 UnitySerializationHolder.GetTypeData (this, info, context);
636 public override string ToString()
638 return getFullName (false, false);
641 [MethodImplAttribute(MethodImplOptions.InternalCall)]
642 public extern override Type [] GetGenericArguments ();
644 public override bool ContainsGenericParameters {
646 if (IsGenericParameter)
650 foreach (Type arg in GetGenericArguments ())
651 if (arg.ContainsGenericParameters)
656 return GetElementType ().ContainsGenericParameters;
662 public extern override bool IsGenericParameter {
663 [MethodImplAttribute(MethodImplOptions.InternalCall)]
667 public extern override MethodBase DeclaringMethod {
668 [MethodImplAttribute(MethodImplOptions.InternalCall)]
672 public override Type GetGenericTypeDefinition () {
673 Type res = GetGenericTypeDefinition_impl ();
675 throw new InvalidOperationException ();
681 public override IList<CustomAttributeData> GetCustomAttributesData () {
682 return CustomAttributeData.GetCustomAttributes (this);
686 public override Array GetEnumValues () {
688 throw new ArgumentException ("Type is not an enumeration", "enumType");
690 return Enum.GetValues (this);
694 static MethodBase CheckMethodSecurity (MethodBase mb)
699 if (!SecurityManager.SecurityEnabled || (mb == null))
702 // Sadly we have no way to know which kind of security action this is
703 // so we must do it the hard way. Actually this isn't so bad
704 // because we can skip the (mb.Attributes & MethodAttributes.HasSecurity)
705 // icall required (and do it ourselves)
707 // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
708 return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
713 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
714 [MethodImplAttribute(MethodImplOptions.InternalCall)]
715 public extern int get_core_clr_security_level ();
717 public override bool IsSecurityTransparent
719 get { return get_core_clr_security_level () == 0; }
722 public override bool IsSecurityCritical
724 get { return get_core_clr_security_level () > 0; }
727 public override bool IsSecuritySafeCritical
729 get { return get_core_clr_security_level () == 1; }
732 public override StructLayoutAttribute StructLayoutAttribute {
734 return GetStructLayoutAttribute ();
739 internal override bool IsUserType {