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.Globalization;
34 using System.Reflection;
35 using System.Runtime.CompilerServices;
36 using System.Runtime.Serialization;
37 using System.Security;
42 internal class MonoType : Type, ISerializable
45 [MethodImplAttribute(MethodImplOptions.InternalCall)]
46 private static extern void type_from_obj (MonoType type, Object obj);
48 internal MonoType (Object obj)
50 // this should not be used - lupus
51 type_from_obj (this, obj);
53 throw new NotImplementedException ();
56 [MethodImplAttribute(MethodImplOptions.InternalCall)]
57 private static extern TypeAttributes get_attributes (Type type);
59 protected override TypeAttributes GetAttributeFlagsImpl ()
61 return get_attributes (this);
64 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
66 CallingConventions callConvention,
68 ParameterModifier[] modifiers)
70 if (bindingAttr == BindingFlags.Default)
71 bindingAttr = BindingFlags.Public | BindingFlags.Instance;
73 ConstructorInfo[] methods = GetConstructors (bindingAttr);
74 ConstructorInfo found = null;
77 foreach (ConstructorInfo m in methods) {
78 // Under MS.NET, Standard|HasThis matches Standard...
79 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
88 throw new AmbiguousMatchException ();
89 return (ConstructorInfo) CheckMethodSecurity (found);
91 match = new MethodBase [count];
96 foreach (ConstructorInfo m in methods) {
97 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
103 binder = Binder.DefaultBinder;
104 return (ConstructorInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
107 [MethodImplAttribute(MethodImplOptions.InternalCall)]
108 internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
110 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
112 return GetConstructors_internal (bindingAttr, this);
115 [MethodImplAttribute(MethodImplOptions.InternalCall)]
116 extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
118 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
121 throw new ArgumentNullException ("name");
123 return InternalGetEvent (name, bindingAttr);
126 [MethodImplAttribute(MethodImplOptions.InternalCall)]
127 internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
129 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
131 return GetEvents_internal (bindingAttr, this);
134 [MethodImplAttribute(MethodImplOptions.InternalCall)]
135 public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
137 [MethodImplAttribute(MethodImplOptions.InternalCall)]
138 internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
140 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
142 return GetFields_internal (bindingAttr, this);
145 public override Type GetInterface (string name, bool ignoreCase)
148 throw new ArgumentNullException ();
150 Type[] interfaces = GetInterfaces();
152 foreach (Type type in interfaces) {
153 if (String.Compare (type.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
155 if (String.Compare (type.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
162 [MethodImplAttribute(MethodImplOptions.InternalCall)]
163 public extern override Type[] GetInterfaces();
165 public override MemberInfo[] GetMembers( BindingFlags bindingAttr)
167 return FindMembers (MemberTypes.All, bindingAttr, null, null);
170 [MethodImplAttribute(MethodImplOptions.InternalCall)]
171 internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
173 public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
175 return GetMethodsByName (null, bindingAttr, false, this);
178 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
180 CallingConventions callConvention,
181 Type[] types, ParameterModifier[] modifiers)
183 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
184 MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
185 MethodInfo found = null;
189 foreach (MethodInfo m in methods) {
190 // Under MS.NET, Standard|HasThis matches Standard...
191 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
200 if (count == 1 && types == null)
201 return (MethodInfo) CheckMethodSecurity (found);
203 match = new MethodBase [count];
208 foreach (MethodInfo m in methods) {
209 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
216 return (MethodInfo) CheckMethodSecurity (Binder.FindMostDerivedMatch (match));
219 binder = Binder.DefaultBinder;
221 return (MethodInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
224 [MethodImplAttribute(MethodImplOptions.InternalCall)]
225 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
227 [MethodImplAttribute(MethodImplOptions.InternalCall)]
228 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
230 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
232 return GetCorrespondingInflatedMethod (fromNoninstanciated);
235 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
237 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
240 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
242 /* create sensible flags from given FieldInfo */
243 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
244 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
245 return GetField (fromNoninstanciated.Name, flags);
248 [MethodImplAttribute(MethodImplOptions.InternalCall)]
249 public extern override Type GetNestedType (string name, BindingFlags bindingAttr);
251 [MethodImplAttribute(MethodImplOptions.InternalCall)]
252 public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
254 [MethodImplAttribute(MethodImplOptions.InternalCall)]
255 internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
257 public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
259 return GetPropertiesByName (null, bindingAttr, false, this);
262 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
263 Binder binder, Type returnType,
265 ParameterModifier[] modifiers)
267 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
268 PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
269 int count = props.Length;
273 if (count == 1 && (types == null || types.Length == 0) &&
274 (returnType == null || returnType == props[0].PropertyType))
278 binder = Binder.DefaultBinder;
280 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
283 protected override bool HasElementTypeImpl ()
285 return IsArrayImpl() || IsByRefImpl() || IsPointerImpl ();
288 protected override bool IsArrayImpl ()
290 return Type.IsArrayImpl (this);
293 [MethodImplAttribute(MethodImplOptions.InternalCall)]
294 protected extern override bool IsByRefImpl ();
296 [MethodImplAttribute (MethodImplOptions.InternalCall)]
297 protected extern override bool IsCOMObjectImpl ();
299 [MethodImplAttribute(MethodImplOptions.InternalCall)]
300 protected extern override bool IsPointerImpl ();
302 [MethodImplAttribute(MethodImplOptions.InternalCall)]
303 protected extern override bool IsPrimitiveImpl ();
305 public override bool IsSubclassOf (Type type)
308 throw new ArgumentNullException ("type");
310 return base.IsSubclassOf (type);
313 public override object InvokeMember (string name, BindingFlags invokeAttr,
314 Binder binder, object target, object[] args,
315 ParameterModifier[] modifiers,
316 CultureInfo culture, string[] namedParameters)
319 const string bindingflags_arg = "bindingFlags";
321 const string bindingflags_arg = "invokeAttr";
325 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
326 if ((invokeAttr & (BindingFlags.GetField |
327 BindingFlags.GetField | BindingFlags.GetProperty |
328 BindingFlags.SetProperty)) != 0)
329 throw new ArgumentException (bindingflags_arg);
330 } else if (name == null)
331 throw new ArgumentNullException ("name");
332 if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
333 throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg);
334 if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
335 throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg);
336 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
337 if ((invokeAttr & BindingFlags.SetField) != 0)
338 throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg);
339 if ((invokeAttr & BindingFlags.SetProperty) != 0)
340 throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg);
342 if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
343 throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
344 if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0)
345 throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg);
347 /* set some defaults if none are provided :-( */
348 if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
349 invokeAttr |= BindingFlags.Public;
350 if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0)
351 invokeAttr |= BindingFlags.Static|BindingFlags.Instance;
354 binder = Binder.DefaultBinder;
355 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
356 /* the name is ignored */
357 invokeAttr |= BindingFlags.DeclaredOnly;
358 ConstructorInfo[] ctors = GetConstructors (invokeAttr);
360 MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state);
362 if (this.IsValueType && args == null)
363 return Activator.CreateInstanceInternal (this);
365 throw new MissingMethodException ("Constructor on type '" + FullName + "' not found.");
367 object result = ctor.Invoke (target, invokeAttr, binder, args, culture);
368 binder.ReorderArgumentArray (ref args, state);
371 if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) {
372 DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute));
373 name = attr.MemberName;
375 bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
376 string throwMissingMethodDescription = null;
377 bool throwMissingFieldException = false;
379 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
380 MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
383 args = new object [0];
384 MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
386 if (methods.Length > 0)
387 throwMissingMethodDescription = "The best match for method " + name + " has some invalid parameter.";
389 throwMissingMethodDescription = "Cannot find method " + name + ".";
391 ParameterInfo[] parameters = m.GetParameters();
392 for (int i = 0; i < parameters.Length; ++i) {
393 if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault)
394 throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters");
396 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
397 typeof (ParamArrayAttribute)) : false;
399 ReorderParamArrayArguments (ref args, m);
400 object result = m.Invoke (target, invokeAttr, binder, args, culture);
401 binder.ReorderArgumentArray (ref args, state);
405 if ((invokeAttr & BindingFlags.GetField) != 0) {
406 FieldInfo f = GetField (name, invokeAttr);
408 return f.GetValue (target);
409 } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
410 throwMissingFieldException = true;
412 /* try GetProperty */
413 } else if ((invokeAttr & BindingFlags.SetField) != 0) {
414 FieldInfo f = GetField (name, invokeAttr);
418 throw new ArgumentNullException ("providedArgs");
420 if ((args == null) || args.Length != 1)
421 throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg);
422 f.SetValue (target, args [0]);
424 } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
425 throwMissingFieldException = true;
427 /* try SetProperty */
429 if ((invokeAttr & BindingFlags.GetProperty) != 0) {
430 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
433 for (i = 0; i < properties.Length; ++i) {
434 if ((properties [i].GetGetMethod (true) != null))
437 MethodBase[] smethods = new MethodBase [count];
439 for (i = 0; i < properties.Length; ++i) {
440 MethodBase mb = properties [i].GetGetMethod (true);
442 smethods [count++] = mb;
444 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
446 throwMissingFieldException = true;
448 ParameterInfo[] parameters = m.GetParameters();
449 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
450 typeof (ParamArrayAttribute)) : false;
452 ReorderParamArrayArguments (ref args, m);
453 object result = m.Invoke (target, invokeAttr, binder, args, culture);
454 binder.ReorderArgumentArray (ref args, state);
457 } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
458 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
461 for (i = 0; i < properties.Length; ++i) {
462 if (properties [i].GetSetMethod (true) != null)
465 MethodBase[] smethods = new MethodBase [count];
467 for (i = 0; i < properties.Length; ++i) {
468 MethodBase mb = properties [i].GetSetMethod (true);
470 smethods [count++] = mb;
472 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
474 throwMissingFieldException = true;
476 ParameterInfo[] parameters = m.GetParameters();
477 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
478 typeof (ParamArrayAttribute)) : false;
480 ReorderParamArrayArguments (ref args, m);
481 object result = m.Invoke (target, invokeAttr, binder, args, culture);
482 binder.ReorderArgumentArray (ref args, state);
486 if (throwMissingMethodDescription != null)
487 throw new MissingMethodException(throwMissingMethodDescription);
488 if (throwMissingFieldException)
489 throw new MissingFieldException("Cannot find variable " + name + ".");
494 [MethodImplAttribute(MethodImplOptions.InternalCall)]
495 public extern override Type GetElementType ();
497 public override Type UnderlyingSystemType {
499 // This has _nothing_ to do with getting the base type of an enum etc.
504 public extern override Assembly Assembly {
505 [MethodImplAttribute(MethodImplOptions.InternalCall)]
509 public override string AssemblyQualifiedName {
511 return getFullName (true, true);
515 [MethodImplAttribute(MethodImplOptions.InternalCall)]
516 private extern string getFullName(bool full_name, bool assembly_qualified);
518 public extern override Type BaseType {
519 [MethodImplAttribute(MethodImplOptions.InternalCall)]
523 public override string FullName {
525 return getFullName (true, false);
529 public override Guid GUID {
531 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
534 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
538 public override bool IsDefined (Type attributeType, bool inherit)
540 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
543 public override object[] GetCustomAttributes (bool inherit)
545 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
548 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
550 if (attributeType == null)
552 throw new ArgumentNullException("attributeType");
555 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
558 public override MemberTypes MemberType {
560 if (DeclaringType != null)
561 return MemberTypes.NestedType;
563 return MemberTypes.TypeInfo;
567 public extern override string Name {
568 [MethodImplAttribute(MethodImplOptions.InternalCall)]
572 public extern override string Namespace {
573 [MethodImplAttribute(MethodImplOptions.InternalCall)]
577 public extern override Module Module {
578 [MethodImplAttribute(MethodImplOptions.InternalCall)]
582 public extern override Type DeclaringType {
583 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587 public override Type ReflectedType {
589 return DeclaringType;
593 public override RuntimeTypeHandle TypeHandle {
599 [MethodImplAttribute(MethodImplOptions.InternalCall)]
600 public extern override int GetArrayRank ();
602 public void GetObjectData(SerializationInfo info, StreamingContext context)
604 UnitySerializationHolder.GetTypeData (this, info, context);
607 public override string ToString()
609 return getFullName (false, false);
612 #if NET_2_0 || BOOTSTRAP_NET_2_0
613 [MethodImplAttribute(MethodImplOptions.InternalCall)]
614 public extern override Type [] GetGenericArguments ();
616 public override bool ContainsGenericParameters {
618 if (IsGenericParameter)
622 foreach (Type arg in GetGenericArguments ())
623 if (arg.ContainsGenericParameters)
628 return GetElementType ().ContainsGenericParameters;
634 public extern override bool IsGenericParameter {
635 [MethodImplAttribute(MethodImplOptions.InternalCall)]
639 public extern override MethodBase DeclaringMethod {
640 [MethodImplAttribute(MethodImplOptions.InternalCall)]
645 private MethodBase CheckMethodSecurity (MethodBase mb)
650 if (!SecurityManager.SecurityEnabled || (mb == null))
653 // Sadly we have no way to know which kind of security action this is
654 // so we must do it the hard way. Actually this isn't so bad
655 // because we can skip the (mb.Attributes & MethodAttributes.HasSecurity)
656 // icall required (and do it ourselves)
658 // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
659 return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
663 void ReorderParamArrayArguments(ref object[] args, MethodBase method)
665 ParameterInfo[] parameters = method.GetParameters();
666 object[] newArgs = new object [parameters.Length];
667 Array paramArray = Array.CreateInstance(parameters[parameters.Length - 1].ParameterType.GetElementType(),
668 args.Length - (parameters.Length - 1));
669 int paramArrayCount = 0;
670 for (int i = 0; i < args.Length; i++) {
671 if (i < (parameters.Length - 1))
672 newArgs [i] = args [i];
674 paramArray.SetValue (args [i], paramArrayCount);
678 newArgs [parameters.Length - 1] = paramArray;