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.CompilerServices;
37 using System.Runtime.Serialization;
38 using System.Security;
42 // Contains information about the type which is expensive to compute
43 internal class MonoTypeInfo {
44 public string full_name;
45 public ConstructorInfo default_ctor;
49 internal class MonoType : Type, ISerializable
52 MonoTypeInfo type_info;
54 [MethodImplAttribute(MethodImplOptions.InternalCall)]
55 private static extern void type_from_obj (MonoType type, Object obj);
57 internal MonoType (Object obj)
59 // this should not be used - lupus
60 type_from_obj (this, obj);
62 throw new NotImplementedException ();
65 [MethodImplAttribute(MethodImplOptions.InternalCall)]
66 private static extern TypeAttributes get_attributes (Type type);
68 internal ConstructorInfo GetDefaultConstructor () {
69 ConstructorInfo ctor = null;
71 if (type_info == null)
72 type_info = new MonoTypeInfo ();
73 if ((ctor = type_info.default_ctor) == null) {
74 const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;
76 ctor = type_info.default_ctor = GetConstructor (flags, null, CallingConventions.Any, Type.EmptyTypes, null);
82 protected override TypeAttributes GetAttributeFlagsImpl ()
84 return get_attributes (this);
87 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
89 CallingConventions callConvention,
91 ParameterModifier[] modifiers)
93 ConstructorInfo[] methods = GetConstructors (bindingAttr);
94 return GetConstructorImpl (methods, bindingAttr, binder, callConvention, types, modifiers);
97 internal static ConstructorInfo GetConstructorImpl (ConstructorInfo[] methods, BindingFlags bindingAttr,
99 CallingConventions callConvention,
101 ParameterModifier[] modifiers)
103 if (bindingAttr == BindingFlags.Default)
104 bindingAttr = BindingFlags.Public | BindingFlags.Instance;
106 ConstructorInfo found = null;
109 foreach (ConstructorInfo m in methods) {
110 // Under MS.NET, Standard|HasThis matches Standard...
111 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
120 throw new AmbiguousMatchException ();
121 return (ConstructorInfo) CheckMethodSecurity (found);
123 match = new MethodBase [count];
128 foreach (ConstructorInfo m in methods) {
129 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
135 binder = Binder.DefaultBinder;
136 return (ConstructorInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
139 [MethodImplAttribute(MethodImplOptions.InternalCall)]
140 internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
142 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
144 return GetConstructors_internal (bindingAttr, this);
147 [MethodImplAttribute(MethodImplOptions.InternalCall)]
148 extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
150 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
153 throw new ArgumentNullException ("name");
155 return InternalGetEvent (name, bindingAttr);
158 [MethodImplAttribute(MethodImplOptions.InternalCall)]
159 internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
161 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
163 return GetEvents_internal (bindingAttr, this);
166 [MethodImplAttribute(MethodImplOptions.InternalCall)]
167 public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
169 [MethodImplAttribute(MethodImplOptions.InternalCall)]
170 internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
172 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
174 return GetFields_internal (bindingAttr, this);
177 public override Type GetInterface (string name, bool ignoreCase)
180 throw new ArgumentNullException ();
182 Type[] interfaces = GetInterfaces();
184 foreach (Type type in interfaces) {
185 if (String.Compare (type.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
187 if (String.Compare (type.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
194 [MethodImplAttribute(MethodImplOptions.InternalCall)]
195 public extern override Type[] GetInterfaces();
197 public override MemberInfo[] GetMembers( BindingFlags bindingAttr)
199 return FindMembers (MemberTypes.All, bindingAttr, null, null);
202 [MethodImplAttribute(MethodImplOptions.InternalCall)]
203 internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
205 public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
207 return GetMethodsByName (null, bindingAttr, false, this);
210 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
212 CallingConventions callConvention,
213 Type[] types, ParameterModifier[] modifiers)
215 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
216 MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
217 MethodInfo found = null;
221 foreach (MethodInfo m in methods) {
222 // Under MS.NET, Standard|HasThis matches Standard...
223 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
232 if (count == 1 && types == null)
233 return (MethodInfo) CheckMethodSecurity (found);
235 match = new MethodBase [count];
240 foreach (MethodInfo m in methods) {
241 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
248 return (MethodInfo) CheckMethodSecurity (Binder.FindMostDerivedMatch (match));
251 binder = Binder.DefaultBinder;
253 return (MethodInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
256 [MethodImplAttribute(MethodImplOptions.InternalCall)]
257 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
259 [MethodImplAttribute(MethodImplOptions.InternalCall)]
260 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
262 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
264 if (fromNoninstanciated == null)
265 throw new ArgumentNullException ("fromNoninstanciated");
266 return GetCorrespondingInflatedMethod (fromNoninstanciated);
269 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
271 if (fromNoninstanciated == null)
272 throw new ArgumentNullException ("fromNoninstanciated");
273 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
276 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
278 /* create sensible flags from given FieldInfo */
279 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
280 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
281 return GetField (fromNoninstanciated.Name, flags);
284 [MethodImplAttribute(MethodImplOptions.InternalCall)]
285 public extern override Type GetNestedType (string name, BindingFlags bindingAttr);
287 [MethodImplAttribute(MethodImplOptions.InternalCall)]
288 public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
290 [MethodImplAttribute(MethodImplOptions.InternalCall)]
291 internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
293 public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
295 return GetPropertiesByName (null, bindingAttr, false, this);
298 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
299 Binder binder, Type returnType,
301 ParameterModifier[] modifiers)
303 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
304 PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
305 int count = props.Length;
309 if (count == 1 && (types == null || types.Length == 0) &&
310 (returnType == null || returnType == props[0].PropertyType))
314 binder = Binder.DefaultBinder;
316 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
319 protected override bool HasElementTypeImpl ()
321 return IsArrayImpl() || IsByRefImpl() || IsPointerImpl ();
324 protected override bool IsArrayImpl ()
326 return Type.IsArrayImpl (this);
329 [MethodImplAttribute(MethodImplOptions.InternalCall)]
330 protected extern override bool IsByRefImpl ();
332 [MethodImplAttribute (MethodImplOptions.InternalCall)]
333 protected extern override bool IsCOMObjectImpl ();
335 [MethodImplAttribute(MethodImplOptions.InternalCall)]
336 protected extern override bool IsPointerImpl ();
338 [MethodImplAttribute(MethodImplOptions.InternalCall)]
339 protected extern override bool IsPrimitiveImpl ();
341 public override bool IsSubclassOf (Type type)
344 throw new ArgumentNullException ("type");
346 return base.IsSubclassOf (type);
349 public override object InvokeMember (string name, BindingFlags invokeAttr,
350 Binder binder, object target, object[] args,
351 ParameterModifier[] modifiers,
352 CultureInfo culture, string[] namedParameters)
354 const string bindingflags_arg = "bindingFlags";
357 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
358 if ((invokeAttr & (BindingFlags.GetField |
359 BindingFlags.GetField | BindingFlags.GetProperty |
360 BindingFlags.SetProperty)) != 0)
361 throw new ArgumentException (bindingflags_arg);
362 } else if (name == null)
363 throw new ArgumentNullException ("name");
364 if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
365 throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg);
366 if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
367 throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg);
368 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
369 if ((invokeAttr & BindingFlags.SetField) != 0)
370 throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg);
371 if ((invokeAttr & BindingFlags.SetProperty) != 0)
372 throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg);
374 if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
375 throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
376 if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0)
377 throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg);
379 /* set some defaults if none are provided :-( */
380 if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
381 invokeAttr |= BindingFlags.Public;
382 if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0)
383 invokeAttr |= BindingFlags.Static|BindingFlags.Instance;
386 binder = Binder.DefaultBinder;
387 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
388 /* the name is ignored */
389 invokeAttr |= BindingFlags.DeclaredOnly;
390 ConstructorInfo[] ctors = GetConstructors (invokeAttr);
392 MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state);
394 if (this.IsValueType && args == null)
395 return Activator.CreateInstanceInternal (this);
397 throw new MissingMethodException ("Constructor on type '" + FullName + "' not found.");
399 object result = ctor.Invoke (target, invokeAttr, binder, args, culture);
400 binder.ReorderArgumentArray (ref args, state);
403 if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) {
404 DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute));
405 name = attr.MemberName;
407 bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
408 string throwMissingMethodDescription = null;
409 bool throwMissingFieldException = false;
411 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
412 MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
415 args = new object [0];
416 MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
418 if (methods.Length > 0)
419 throwMissingMethodDescription = "The best match for method " + name + " has some invalid parameter.";
421 throwMissingMethodDescription = "Cannot find method " + name + ".";
423 ParameterInfo[] parameters = m.GetParameters();
424 for (int i = 0; i < parameters.Length; ++i) {
425 if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault)
426 throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters");
428 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
429 typeof (ParamArrayAttribute)) : false;
431 ReorderParamArrayArguments (ref args, m);
432 object result = m.Invoke (target, invokeAttr, binder, args, culture);
433 binder.ReorderArgumentArray (ref args, state);
437 if ((invokeAttr & BindingFlags.GetField) != 0) {
438 FieldInfo f = GetField (name, invokeAttr);
440 return f.GetValue (target);
441 } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
442 throwMissingFieldException = true;
444 /* try GetProperty */
445 } else if ((invokeAttr & BindingFlags.SetField) != 0) {
446 FieldInfo f = GetField (name, invokeAttr);
449 throw new ArgumentNullException ("providedArgs");
450 if ((args == null) || args.Length != 1)
451 throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg);
452 f.SetValue (target, args [0]);
454 } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
455 throwMissingFieldException = true;
457 /* try SetProperty */
459 if ((invokeAttr & BindingFlags.GetProperty) != 0) {
460 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
463 for (i = 0; i < properties.Length; ++i) {
464 if ((properties [i].GetGetMethod (true) != null))
467 MethodBase[] smethods = new MethodBase [count];
469 for (i = 0; i < properties.Length; ++i) {
470 MethodBase mb = properties [i].GetGetMethod (true);
472 smethods [count++] = mb;
474 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
476 throwMissingFieldException = true;
478 ParameterInfo[] parameters = m.GetParameters();
479 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
480 typeof (ParamArrayAttribute)) : false;
482 ReorderParamArrayArguments (ref args, m);
483 object result = m.Invoke (target, invokeAttr, binder, args, culture);
484 binder.ReorderArgumentArray (ref args, state);
487 } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
488 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
491 for (i = 0; i < properties.Length; ++i) {
492 if (properties [i].GetSetMethod (true) != null)
495 MethodBase[] smethods = new MethodBase [count];
497 for (i = 0; i < properties.Length; ++i) {
498 MethodBase mb = properties [i].GetSetMethod (true);
500 smethods [count++] = mb;
502 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
504 throwMissingFieldException = true;
506 ParameterInfo[] parameters = m.GetParameters();
507 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
508 typeof (ParamArrayAttribute)) : false;
510 ReorderParamArrayArguments (ref args, m);
511 object result = m.Invoke (target, invokeAttr, binder, args, culture);
512 binder.ReorderArgumentArray (ref args, state);
516 if (throwMissingMethodDescription != null)
517 throw new MissingMethodException(throwMissingMethodDescription);
518 if (throwMissingFieldException)
519 throw new MissingFieldException("Cannot find variable " + name + ".");
524 [MethodImplAttribute(MethodImplOptions.InternalCall)]
525 public extern override Type GetElementType ();
527 public override Type UnderlyingSystemType {
529 // This has _nothing_ to do with getting the base type of an enum etc.
534 public extern override Assembly Assembly {
535 [MethodImplAttribute(MethodImplOptions.InternalCall)]
539 public override string AssemblyQualifiedName {
541 return getFullName (true, true);
545 [MethodImplAttribute(MethodImplOptions.InternalCall)]
546 private extern string getFullName(bool full_name, bool assembly_qualified);
548 public extern override Type BaseType {
549 [MethodImplAttribute(MethodImplOptions.InternalCall)]
553 public override string FullName {
556 // This doesn't need locking
557 if (type_info == null)
558 type_info = new MonoTypeInfo ();
559 if ((fullName = type_info.full_name) == null)
560 fullName = type_info.full_name = getFullName (true, false);
566 public override Guid GUID {
568 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
571 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
575 public override bool IsDefined (Type attributeType, bool inherit)
577 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
580 public override object[] GetCustomAttributes (bool inherit)
582 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
585 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
587 if (attributeType == null)
589 throw new ArgumentNullException("attributeType");
592 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
595 public override MemberTypes MemberType {
597 if (DeclaringType != null && !IsGenericParameter)
598 return MemberTypes.NestedType;
600 return MemberTypes.TypeInfo;
604 public extern override string Name {
605 [MethodImplAttribute(MethodImplOptions.InternalCall)]
609 public extern override string Namespace {
610 [MethodImplAttribute(MethodImplOptions.InternalCall)]
614 public extern override Module Module {
615 [MethodImplAttribute(MethodImplOptions.InternalCall)]
619 public extern override Type DeclaringType {
620 [MethodImplAttribute(MethodImplOptions.InternalCall)]
624 public override Type ReflectedType {
626 return DeclaringType;
630 public override RuntimeTypeHandle TypeHandle {
636 [MethodImplAttribute(MethodImplOptions.InternalCall)]
637 public extern override int GetArrayRank ();
639 public void GetObjectData(SerializationInfo info, StreamingContext context)
641 UnitySerializationHolder.GetTypeData (this, info, context);
644 public override string ToString()
646 return getFullName (false, false);
649 [MethodImplAttribute(MethodImplOptions.InternalCall)]
650 public extern override Type [] GetGenericArguments ();
652 public override bool ContainsGenericParameters {
654 if (IsGenericParameter)
658 foreach (Type arg in GetGenericArguments ())
659 if (arg.ContainsGenericParameters)
664 return GetElementType ().ContainsGenericParameters;
670 public extern override bool IsGenericParameter {
671 [MethodImplAttribute(MethodImplOptions.InternalCall)]
675 public extern override MethodBase DeclaringMethod {
676 [MethodImplAttribute(MethodImplOptions.InternalCall)]
680 public override Type GetGenericTypeDefinition () {
681 Type res = GetGenericTypeDefinition_impl ();
683 throw new InvalidOperationException ();
689 public override IList<CustomAttributeData> GetCustomAttributesData () {
690 return CustomAttributeData.GetCustomAttributes (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;
712 void ReorderParamArrayArguments(ref object[] args, MethodBase method)
714 ParameterInfo[] parameters = method.GetParameters();
715 object[] newArgs = new object [parameters.Length];
716 Array paramArray = Array.CreateInstance(parameters[parameters.Length - 1].ParameterType.GetElementType(),
717 args.Length - (parameters.Length - 1));
718 int paramArrayCount = 0;
719 for (int i = 0; i < args.Length; i++) {
720 if (i < (parameters.Length - 1))
721 newArgs [i] = args [i];
723 paramArray.SetValue (args [i], paramArrayCount);
727 newArgs [parameters.Length - 1] = paramArray;