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;
41 // Contains information about the type which is expensive to compute
42 internal class MonoTypeInfo {
43 public string full_name;
44 public ConstructorInfo default_ctor;
48 internal class MonoType : Type, ISerializable
51 MonoTypeInfo type_info;
53 [MethodImplAttribute(MethodImplOptions.InternalCall)]
54 private static extern void type_from_obj (MonoType type, Object obj);
56 internal MonoType (Object obj)
58 // this should not be used - lupus
59 type_from_obj (this, obj);
61 throw new NotImplementedException ();
64 [MethodImplAttribute(MethodImplOptions.InternalCall)]
65 private static extern TypeAttributes get_attributes (Type type);
67 internal ConstructorInfo GetDefaultConstructor () {
68 ConstructorInfo ctor = null;
70 if (type_info == null)
71 type_info = new MonoTypeInfo ();
72 if ((ctor = type_info.default_ctor) == null) {
73 const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;
75 ctor = type_info.default_ctor = GetConstructor (flags, null, CallingConventions.Any, Type.EmptyTypes, null);
81 protected override TypeAttributes GetAttributeFlagsImpl ()
83 return get_attributes (this);
86 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
88 CallingConventions callConvention,
90 ParameterModifier[] modifiers)
92 ConstructorInfo[] methods = GetConstructors (bindingAttr);
93 return GetConstructorImpl (methods, bindingAttr, binder, callConvention, types, modifiers);
96 internal static ConstructorInfo GetConstructorImpl (ConstructorInfo[] methods, BindingFlags bindingAttr,
98 CallingConventions callConvention,
100 ParameterModifier[] modifiers)
102 if (bindingAttr == BindingFlags.Default)
103 bindingAttr = BindingFlags.Public | BindingFlags.Instance;
105 ConstructorInfo found = null;
108 foreach (ConstructorInfo m in methods) {
109 // Under MS.NET, Standard|HasThis matches Standard...
110 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
119 throw new AmbiguousMatchException ();
120 return (ConstructorInfo) CheckMethodSecurity (found);
122 match = new MethodBase [count];
127 foreach (ConstructorInfo m in methods) {
128 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
134 binder = Binder.DefaultBinder;
135 return (ConstructorInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
138 [MethodImplAttribute(MethodImplOptions.InternalCall)]
139 internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
141 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
143 return GetConstructors_internal (bindingAttr, this);
146 [MethodImplAttribute(MethodImplOptions.InternalCall)]
147 extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
149 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
152 throw new ArgumentNullException ("name");
154 return InternalGetEvent (name, bindingAttr);
157 [MethodImplAttribute(MethodImplOptions.InternalCall)]
158 internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
160 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
162 return GetEvents_internal (bindingAttr, this);
165 [MethodImplAttribute(MethodImplOptions.InternalCall)]
166 public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
168 [MethodImplAttribute(MethodImplOptions.InternalCall)]
169 internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
171 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
173 return GetFields_internal (bindingAttr, this);
176 public override Type GetInterface (string name, bool ignoreCase)
179 throw new ArgumentNullException ();
181 Type[] interfaces = GetInterfaces();
183 foreach (Type type in interfaces) {
184 if (String.Compare (type.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
186 if (String.Compare (type.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
193 [MethodImplAttribute(MethodImplOptions.InternalCall)]
194 public extern override Type[] GetInterfaces();
196 public override MemberInfo[] GetMembers( BindingFlags bindingAttr)
198 return FindMembers (MemberTypes.All, bindingAttr, null, null);
201 [MethodImplAttribute(MethodImplOptions.InternalCall)]
202 internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
204 public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
206 return GetMethodsByName (null, bindingAttr, false, this);
209 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
211 CallingConventions callConvention,
212 Type[] types, ParameterModifier[] modifiers)
214 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
215 MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
216 MethodInfo found = null;
220 foreach (MethodInfo m in methods) {
221 // Under MS.NET, Standard|HasThis matches Standard...
222 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
231 if (count == 1 && types == null)
232 return (MethodInfo) CheckMethodSecurity (found);
234 match = new MethodBase [count];
239 foreach (MethodInfo m in methods) {
240 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
247 return (MethodInfo) CheckMethodSecurity (Binder.FindMostDerivedMatch (match));
250 binder = Binder.DefaultBinder;
252 return (MethodInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
255 [MethodImplAttribute(MethodImplOptions.InternalCall)]
256 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
258 [MethodImplAttribute(MethodImplOptions.InternalCall)]
259 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
261 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
263 if (fromNoninstanciated == null)
264 throw new ArgumentNullException ("fromNoninstanciated");
265 return GetCorrespondingInflatedMethod (fromNoninstanciated);
268 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
270 if (fromNoninstanciated == null)
271 throw new ArgumentNullException ("fromNoninstanciated");
272 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
275 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
277 /* create sensible flags from given FieldInfo */
278 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
279 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
280 return GetField (fromNoninstanciated.Name, flags);
283 [MethodImplAttribute(MethodImplOptions.InternalCall)]
284 public extern override Type GetNestedType (string name, BindingFlags bindingAttr);
286 [MethodImplAttribute(MethodImplOptions.InternalCall)]
287 public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
289 [MethodImplAttribute(MethodImplOptions.InternalCall)]
290 internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
292 public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
294 return GetPropertiesByName (null, bindingAttr, false, this);
297 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
298 Binder binder, Type returnType,
300 ParameterModifier[] modifiers)
302 bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
303 PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
304 int count = props.Length;
308 if (count == 1 && (types == null || types.Length == 0) &&
309 (returnType == null || returnType == props[0].PropertyType))
313 binder = Binder.DefaultBinder;
315 return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
318 protected override bool HasElementTypeImpl ()
320 return IsArrayImpl() || IsByRefImpl() || IsPointerImpl ();
323 protected override bool IsArrayImpl ()
325 return Type.IsArrayImpl (this);
328 [MethodImplAttribute(MethodImplOptions.InternalCall)]
329 protected extern override bool IsByRefImpl ();
331 [MethodImplAttribute (MethodImplOptions.InternalCall)]
332 protected extern override bool IsCOMObjectImpl ();
334 [MethodImplAttribute(MethodImplOptions.InternalCall)]
335 protected extern override bool IsPointerImpl ();
337 [MethodImplAttribute(MethodImplOptions.InternalCall)]
338 protected extern override bool IsPrimitiveImpl ();
340 public override bool IsSubclassOf (Type type)
343 throw new ArgumentNullException ("type");
345 return base.IsSubclassOf (type);
348 public override object InvokeMember (string name, BindingFlags invokeAttr,
349 Binder binder, object target, object[] args,
350 ParameterModifier[] modifiers,
351 CultureInfo culture, string[] namedParameters)
353 const string bindingflags_arg = "bindingFlags";
356 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
357 if ((invokeAttr & (BindingFlags.GetField |
358 BindingFlags.GetField | BindingFlags.GetProperty |
359 BindingFlags.SetProperty)) != 0)
360 throw new ArgumentException (bindingflags_arg);
361 } else if (name == null)
362 throw new ArgumentNullException ("name");
363 if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
364 throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg);
365 if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
366 throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg);
367 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
368 if ((invokeAttr & BindingFlags.SetField) != 0)
369 throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg);
370 if ((invokeAttr & BindingFlags.SetProperty) != 0)
371 throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg);
373 if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
374 throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
375 if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0)
376 throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg);
378 /* set some defaults if none are provided :-( */
379 if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
380 invokeAttr |= BindingFlags.Public;
381 if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0)
382 invokeAttr |= BindingFlags.Static|BindingFlags.Instance;
385 binder = Binder.DefaultBinder;
386 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
387 /* the name is ignored */
388 invokeAttr |= BindingFlags.DeclaredOnly;
389 ConstructorInfo[] ctors = GetConstructors (invokeAttr);
391 MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state);
393 if (this.IsValueType && args == null)
394 return Activator.CreateInstanceInternal (this);
396 throw new MissingMethodException ("Constructor on type '" + FullName + "' not found.");
398 object result = ctor.Invoke (target, invokeAttr, binder, args, culture);
399 binder.ReorderArgumentArray (ref args, state);
402 if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) {
403 DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute));
404 name = attr.MemberName;
406 bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
407 string throwMissingMethodDescription = null;
408 bool throwMissingFieldException = false;
410 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
411 MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
414 args = new object [0];
415 MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
417 if (methods.Length > 0)
418 throwMissingMethodDescription = "The best match for method " + name + " has some invalid parameter.";
420 throwMissingMethodDescription = "Cannot find method " + name + ".";
422 ParameterInfo[] parameters = m.GetParameters();
423 for (int i = 0; i < parameters.Length; ++i) {
424 if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault)
425 throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters");
427 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
428 typeof (ParamArrayAttribute)) : false;
430 ReorderParamArrayArguments (ref args, m);
431 object result = m.Invoke (target, invokeAttr, binder, args, culture);
432 binder.ReorderArgumentArray (ref args, state);
436 if ((invokeAttr & BindingFlags.GetField) != 0) {
437 FieldInfo f = GetField (name, invokeAttr);
439 return f.GetValue (target);
440 } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
441 throwMissingFieldException = true;
443 /* try GetProperty */
444 } else if ((invokeAttr & BindingFlags.SetField) != 0) {
445 FieldInfo f = GetField (name, invokeAttr);
448 throw new ArgumentNullException ("providedArgs");
449 if ((args == null) || args.Length != 1)
450 throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg);
451 f.SetValue (target, args [0]);
453 } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
454 throwMissingFieldException = true;
456 /* try SetProperty */
458 if ((invokeAttr & BindingFlags.GetProperty) != 0) {
459 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
462 for (i = 0; i < properties.Length; ++i) {
463 if ((properties [i].GetGetMethod (true) != null))
466 MethodBase[] smethods = new MethodBase [count];
468 for (i = 0; i < properties.Length; ++i) {
469 MethodBase mb = properties [i].GetGetMethod (true);
471 smethods [count++] = mb;
473 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
475 throwMissingFieldException = true;
477 ParameterInfo[] parameters = m.GetParameters();
478 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
479 typeof (ParamArrayAttribute)) : false;
481 ReorderParamArrayArguments (ref args, m);
482 object result = m.Invoke (target, invokeAttr, binder, args, culture);
483 binder.ReorderArgumentArray (ref args, state);
486 } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
487 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
490 for (i = 0; i < properties.Length; ++i) {
491 if (properties [i].GetSetMethod (true) != null)
494 MethodBase[] smethods = new MethodBase [count];
496 for (i = 0; i < properties.Length; ++i) {
497 MethodBase mb = properties [i].GetSetMethod (true);
499 smethods [count++] = mb;
501 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
503 throwMissingFieldException = true;
505 ParameterInfo[] parameters = m.GetParameters();
506 bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1],
507 typeof (ParamArrayAttribute)) : false;
509 ReorderParamArrayArguments (ref args, m);
510 object result = m.Invoke (target, invokeAttr, binder, args, culture);
511 binder.ReorderArgumentArray (ref args, state);
515 if (throwMissingMethodDescription != null)
516 throw new MissingMethodException(throwMissingMethodDescription);
517 if (throwMissingFieldException)
518 throw new MissingFieldException("Cannot find variable " + name + ".");
523 [MethodImplAttribute(MethodImplOptions.InternalCall)]
524 public extern override Type GetElementType ();
526 public override Type UnderlyingSystemType {
528 // This has _nothing_ to do with getting the base type of an enum etc.
533 public extern override Assembly Assembly {
534 [MethodImplAttribute(MethodImplOptions.InternalCall)]
538 public override string AssemblyQualifiedName {
540 return getFullName (true, true);
544 [MethodImplAttribute(MethodImplOptions.InternalCall)]
545 private extern string getFullName(bool full_name, bool assembly_qualified);
547 public extern override Type BaseType {
548 [MethodImplAttribute(MethodImplOptions.InternalCall)]
552 public override string FullName {
555 // This doesn't need locking
556 if (type_info == null)
557 type_info = new MonoTypeInfo ();
558 if ((fullName = type_info.full_name) == null)
559 fullName = type_info.full_name = getFullName (true, false);
565 public override Guid GUID {
567 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
570 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
574 public override bool IsDefined (Type attributeType, bool inherit)
576 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
579 public override object[] GetCustomAttributes (bool inherit)
581 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
584 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
586 if (attributeType == null)
588 throw new ArgumentNullException("attributeType");
591 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
594 public override MemberTypes MemberType {
596 if (DeclaringType != null && !IsGenericParameter)
597 return MemberTypes.NestedType;
599 return MemberTypes.TypeInfo;
603 public extern override string Name {
604 [MethodImplAttribute(MethodImplOptions.InternalCall)]
608 public extern override string Namespace {
609 [MethodImplAttribute(MethodImplOptions.InternalCall)]
613 public extern override Module Module {
614 [MethodImplAttribute(MethodImplOptions.InternalCall)]
618 public extern override Type DeclaringType {
619 [MethodImplAttribute(MethodImplOptions.InternalCall)]
623 public override Type ReflectedType {
625 return DeclaringType;
629 public override RuntimeTypeHandle TypeHandle {
635 [MethodImplAttribute(MethodImplOptions.InternalCall)]
636 public extern override int GetArrayRank ();
638 public void GetObjectData(SerializationInfo info, StreamingContext context)
640 UnitySerializationHolder.GetTypeData (this, info, context);
643 public override string ToString()
645 return getFullName (false, false);
648 [MethodImplAttribute(MethodImplOptions.InternalCall)]
649 public extern override Type [] GetGenericArguments ();
651 public override bool ContainsGenericParameters {
653 if (IsGenericParameter)
657 foreach (Type arg in GetGenericArguments ())
658 if (arg.ContainsGenericParameters)
663 return GetElementType ().ContainsGenericParameters;
669 public extern override bool IsGenericParameter {
670 [MethodImplAttribute(MethodImplOptions.InternalCall)]
674 public extern override MethodBase DeclaringMethod {
675 [MethodImplAttribute(MethodImplOptions.InternalCall)]
679 public override Type GetGenericTypeDefinition () {
680 Type res = GetGenericTypeDefinition_impl ();
682 throw new InvalidOperationException ();
687 static MethodBase CheckMethodSecurity (MethodBase mb)
692 if (!SecurityManager.SecurityEnabled || (mb == null))
695 // Sadly we have no way to know which kind of security action this is
696 // so we must do it the hard way. Actually this isn't so bad
697 // because we can skip the (mb.Attributes & MethodAttributes.HasSecurity)
698 // icall required (and do it ourselves)
700 // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
701 return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
705 void ReorderParamArrayArguments(ref object[] args, MethodBase method)
707 ParameterInfo[] parameters = method.GetParameters();
708 object[] newArgs = new object [parameters.Length];
709 Array paramArray = Array.CreateInstance(parameters[parameters.Length - 1].ParameterType.GetElementType(),
710 args.Length - (parameters.Length - 1));
711 int paramArrayCount = 0;
712 for (int i = 0; i < args.Length; i++) {
713 if (i < (parameters.Length - 1))
714 newArgs [i] = args [i];
716 paramArray.SetValue (args [i], paramArrayCount);
720 newArgs [parameters.Length - 1] = paramArray;