2004-04-22 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System / MonoType.cs
1 //
2 // System.MonoType
3 //
4 // Authors: 
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 //
10 // (c) 2001-2003 Ximian, Inc.
11 // (c) 2003,2004 Novell, Inc. (http://www.novell.com)
12 //
13
14 using System.Reflection;
15 using System.Runtime.CompilerServices;
16 using System.Globalization;
17 using System.Runtime.Serialization;
18
19 namespace System
20 {
21         [Serializable]
22         internal class MonoType : Type, ISerializable
23         {
24
25                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
26                 private static extern void type_from_obj (MonoType type, Object obj);
27                 
28                 [MonoTODO]
29                 internal MonoType (Object obj)
30                 {
31                         // this should not be used - lupus
32                         type_from_obj (this, obj);
33                         
34                         throw new NotImplementedException ();
35                 }
36
37                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
38                 private static extern TypeAttributes get_attributes (Type type);
39         
40                 protected override TypeAttributes GetAttributeFlagsImpl ()
41                 {
42                         return get_attributes (this);
43                 }
44
45                 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
46                                                                        Binder binder,
47                                                                        CallingConventions callConvention,
48                                                                        Type[] types,
49                                                                        ParameterModifier[] modifiers)
50                 {
51                         if (bindingAttr == BindingFlags.Default)
52                                 bindingAttr = BindingFlags.Public | BindingFlags.Instance;
53
54                         ConstructorInfo[] methods = GetConstructors (bindingAttr);
55                         ConstructorInfo found = null;
56                         MethodBase[] match;
57                         int count = 0;
58                         foreach (ConstructorInfo m in methods) {
59                                 // Under MS.NET, Standard|HasThis matches Standard...
60                                 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
61                                         continue;
62                                 found = m;
63                                 count++;
64                         }
65                         if (count == 0)
66                                 return null;
67                         if (types == null) {
68                                 if (count > 1)
69                                         throw new AmbiguousMatchException ();
70                                 return found;
71                         }
72                         match = new MethodBase [count];
73                         if (count == 1)
74                                 match [0] = found;
75                         else {
76                                 count = 0;
77                                 foreach (ConstructorInfo m in methods) {
78                                         if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
79                                                 continue;
80                                         match [count++] = m;
81                                 }
82                         }
83                         if (binder == null)
84                                 binder = Binder.DefaultBinder;
85                         return (ConstructorInfo)binder.SelectMethod (bindingAttr, match, types, modifiers);
86                 }
87
88                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
89                 internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
90
91                 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
92                 {
93                         return GetConstructors_internal (bindingAttr, this);
94                 }
95
96                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
97                 extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
98
99                 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
100                 {
101                         if (name == null)
102                                 throw new ArgumentNullException ("name");
103
104                         return InternalGetEvent (name, bindingAttr);
105                 }
106
107                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
108                 internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
109
110                 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
111                 {
112                         return GetEvents_internal (bindingAttr, this);
113                 }
114
115                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
116                 public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
117
118                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
119                 internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
120
121                 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
122                 {
123                         return GetFields_internal (bindingAttr, this);
124                 }
125                 
126                 public override Type GetInterface (string name, bool ignoreCase)
127                 {
128                         if (name == null)
129                                 throw new ArgumentNullException ();
130
131                         Type[] interfaces = GetInterfaces();
132
133                         foreach (Type type in interfaces) {
134                                 if (String.Compare (type.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
135                                         return type;
136                                 if (String.Compare (type.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
137                                         return type;
138                         }
139
140                         return null;
141                 }
142
143                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
144                 public extern override Type[] GetInterfaces();
145                 
146                 public override MemberInfo[] GetMembers( BindingFlags bindingAttr)
147                 {
148                         return FindMembers (MemberTypes.All, bindingAttr, null, null);
149                 }
150
151                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
152                 internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
153
154                 public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
155                 {
156                         return GetMethodsByName (null, bindingAttr, false, this);
157                 }
158
159                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
160                                                              Binder binder,
161                                                              CallingConventions callConvention,
162                                                              Type[] types, ParameterModifier[] modifiers)
163                 {
164                         bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
165                         MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
166                         MethodInfo found = null;
167                         MethodBase[] match;
168                         int typesLen = (types != null) ? types.Length : 0;
169                         int count = 0;
170                         
171                         foreach (MethodInfo m in methods) {
172                                 // Under MS.NET, Standard|HasThis matches Standard...
173                                 if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
174                                         continue;
175                                 found = m;
176                                 count++;
177                         }
178
179                         if (count == 0)
180                                 return null;
181                         
182                         if (count == 1 && typesLen == 0) 
183                                 return found;
184
185                         match = new MethodBase [count];
186                         if (count == 1)
187                                 match [0] = found;
188                         else {
189                                 count = 0;
190                                 foreach (MethodInfo m in methods) {
191                                         if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
192                                                 continue;
193                                         match [count++] = m;
194                                 }
195                         }
196                         
197                         if (types == null) 
198                                 return (MethodInfo) Binder.FindMostDerivedMatch (match);
199
200                         if (binder == null)
201                                 binder = Binder.DefaultBinder;
202                         
203                         return (MethodInfo)binder.SelectMethod (bindingAttr, match, types, modifiers);
204                 }
205
206                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
207                 public extern override Type GetNestedType (string name, BindingFlags bindingAttr);
208
209                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
210                 public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
211
212                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
213                 internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
214
215                 public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
216                 {
217                         return GetPropertiesByName (null, bindingAttr, false, this);
218                 }
219
220                 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
221                                                                  Binder binder, Type returnType,
222                                                                  Type[] types,
223                                                                  ParameterModifier[] modifiers)
224                 {
225                         bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
226                         PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
227                         int count = props.Length;
228                         if (count == 0)
229                                 return null;
230                         
231                         if (count == 1 && (types == null || types.Length == 0)) 
232                                 return props [0];
233
234                         if (binder == null)
235                                 binder = Binder.DefaultBinder;
236                         
237                         return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
238                 }
239
240                 protected override bool HasElementTypeImpl ()
241                 {
242                         return IsArrayImpl() || IsByRefImpl() || IsPointerImpl ();
243                 }
244
245                 protected override bool IsArrayImpl ()
246                 {
247                         return Type.IsArrayImpl (this);
248                 }
249
250                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
251                 protected extern override bool IsByRefImpl ();
252
253                 protected override bool IsCOMObjectImpl ()
254                 {
255                         return false;
256                 }
257
258                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
259                 protected extern override bool IsPointerImpl ();
260
261                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
262                 protected extern override bool IsPrimitiveImpl ();
263
264                 protected override bool IsValueTypeImpl ()
265                 {
266                         return type_is_subtype_of (this, typeof (System.ValueType), false) &&
267                                 this != typeof (System.ValueType) &&
268                                 this != typeof (System.Enum);
269                 }
270                 
271                 public override object InvokeMember (string name, BindingFlags invokeAttr,
272                                                      Binder binder, object target, object[] args,
273                                                      ParameterModifier[] modifiers,
274                                                      CultureInfo culture, string[] namedParameters)
275                 {
276
277                         if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
278                                 if ((invokeAttr & (BindingFlags.GetField |
279                                                 BindingFlags.GetField | BindingFlags.GetProperty |
280                                                 BindingFlags.SetProperty)) != 0)
281                                         throw new ArgumentException ("invokeAttr");
282                         } else if (name == null)
283                                 throw new ArgumentNullException ("name");
284                         if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
285                                 throw new ArgumentException ("invokeAttr");
286                         if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
287                                 throw new ArgumentException ("invokeAttr");
288                         if ((invokeAttr & BindingFlags.InvokeMethod) != 0 && (invokeAttr & (BindingFlags.SetProperty|BindingFlags.SetField)) != 0)
289                                 throw new ArgumentException ("invokeAttr");
290                         if ((invokeAttr & BindingFlags.SetField) != 0 && ((args == null) || args.Length != 1))
291                                 throw new ArgumentException ("invokeAttr");
292                         if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
293                                 throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
294
295                         /* set some defaults if none are provided :-( */
296                         if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
297                                 invokeAttr |= BindingFlags.Public;
298                         if ((invokeAttr & (BindingFlags.Static|BindingFlags.Instance)) == 0)
299                                 invokeAttr |= BindingFlags.Static|BindingFlags.Instance;
300
301                         if (binder == null)
302                                 binder = Binder.DefaultBinder;
303                         if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
304                                 /* the name is ignored */
305                                 invokeAttr |= BindingFlags.DeclaredOnly;
306                                 ConstructorInfo[] ctors = GetConstructors (invokeAttr);
307                                 object state = null;
308                                 MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state);
309                                 if (ctor == null)
310                                         throw new MissingMethodException ();
311                                 object result = ctor.Invoke (target, invokeAttr, binder, args, culture);
312                                 binder.ReorderArgumentArray (ref args, state);
313                                 return result;
314                         }
315                         if (name == String.Empty && Attribute.IsDefined (this, typeof (DefaultMemberAttribute))) {
316                                 DefaultMemberAttribute attr = (DefaultMemberAttribute) Attribute.GetCustomAttribute (this, typeof (DefaultMemberAttribute));
317                                 name = attr.MemberName;
318                         }
319                         bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
320                         if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
321                                 MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
322                                 object state = null;
323                                 MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
324                                 if (m == null)
325                                         throw new MissingMethodException ();
326                                 object result = m.Invoke (target, invokeAttr, binder, args, culture);
327                                 binder.ReorderArgumentArray (ref args, state);
328                                 return result;
329                         }
330                         if ((invokeAttr & BindingFlags.GetField) != 0) {
331                                 FieldInfo f = GetField (name, invokeAttr);
332                                 if (f != null) {
333                                         return f.GetValue (target);
334                                 } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
335                                         throw new MissingFieldException ();
336                                 }
337                                 /* try GetProperty */
338                         } else if ((invokeAttr & BindingFlags.SetField) != 0) {
339                                 FieldInfo f = GetField (name, invokeAttr);
340                                 if (f != null) {
341                                         f.SetValue (target, args [0]);
342                                         return null;
343                                 } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
344                                         throw new MissingFieldException ();
345                                 }
346                                 /* try SetProperty */
347                         }
348                         if ((invokeAttr & BindingFlags.GetProperty) != 0) {
349                                 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
350                                 object state = null;
351                                 int i, count = 0;
352                                 for (i = 0; i < properties.Length; ++i) {
353                                         if ((properties [i].GetGetMethod () != null))
354                                                 count++;
355                                 }
356                                 MethodBase[] smethods = new MethodBase [count];
357                                 count = 0;
358                                 for (i = 0; i < properties.Length; ++i) {
359                                         MethodBase mb = properties [i].GetGetMethod ();
360                                         if (mb != null)
361                                                 smethods [count++] = mb;
362                                 }
363                                 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
364                                 if (m == null)
365                                         throw new MissingFieldException ();
366                                 object result = m.Invoke (target, invokeAttr, binder, args, culture);
367                                 binder.ReorderArgumentArray (ref args, state);
368                                 return result;
369                         } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
370                                 PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
371                                 object state = null;
372                                 int i, count = 0;
373                                 for (i = 0; i < properties.Length; ++i) {
374                                         if (properties [i].GetSetMethod () != null)
375                                                 count++;
376                                 }
377                                 MethodBase[] smethods = new MethodBase [count];
378                                 count = 0;
379                                 for (i = 0; i < properties.Length; ++i) {
380                                         MethodBase mb = properties [i].GetSetMethod ();
381                                         if (mb != null)
382                                                 smethods [count++] = mb;
383                                 }
384                                 MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
385                                 if (m == null)
386                                         throw new MissingFieldException ();
387                                 object result = m.Invoke (target, invokeAttr, binder, args, culture);
388                                 binder.ReorderArgumentArray (ref args, state);
389                                 return result;
390                         }
391                         return null;
392                 }
393
394                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
395                 public extern override Type GetElementType ();
396
397                 public extern override Type UnderlyingSystemType {
398                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
399                         get;
400                 }
401
402                 public extern override Assembly Assembly {
403                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
404                         get;
405                 }
406
407                 public override string AssemblyQualifiedName {
408                         get {
409                                 return getFullName () + ", " + Assembly.GetName ().ToString ();
410                         }
411                 }
412
413                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
414                 private extern string getFullName();
415
416                 public extern override Type BaseType {
417                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
418                         get;
419                 }
420
421                 public override string FullName {
422                         get {
423                                 return getFullName ();
424                         }
425                 }
426
427                 public override Guid GUID {
428                         get {
429                                 return Guid.Empty;
430                         }
431                 }
432
433                 public override bool IsDefined (Type attributeType, bool inherit)
434                 {
435                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
436                 }
437
438                 public override object[] GetCustomAttributes (bool inherit)
439                 {
440                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
441                 }
442
443                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
444                 {
445                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
446                 }
447
448                 public override MemberTypes MemberType {
449                         get {
450                                 if (DeclaringType != null)
451                                         return MemberTypes.NestedType;
452                                 else
453                                         return MemberTypes.TypeInfo;
454                         }
455                 }
456
457                 public extern override string Name {
458                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
459                         get;
460                 }
461
462                 public extern override string Namespace {
463                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
464                         get;
465                 }
466
467                 public extern override Module Module {
468                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
469                         get;
470                 }
471
472                 public extern override Type DeclaringType {
473                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
474                         get;
475                 }
476
477                 public override Type ReflectedType {
478                         get {
479                                 return DeclaringType;
480                         }
481                 }
482
483                 public override RuntimeTypeHandle TypeHandle {
484                         get {
485                                 return _impl;
486                         }
487                 }
488
489                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
490                 public extern override int GetArrayRank ();
491
492                 public void GetObjectData(SerializationInfo info, StreamingContext context)
493                 {
494                         UnitySerializationHolder.GetTypeData (this, info, context);
495                 }
496
497 #if NET_2_0 || BOOTSTRAP_NET_1_2
498                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
499                 public extern override Type [] GetGenericArguments ();
500
501                 public extern override bool HasGenericArguments {
502                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
503                         get;
504                 }
505
506                 public override bool ContainsGenericParameters {
507                         get {
508                                 if (IsGenericParameter)
509                                         return true;
510
511                                 if (HasGenericArguments) {
512                                         foreach (Type arg in GetGenericArguments ())
513                                                 if (arg.ContainsGenericParameters)
514                                                         return true;
515                                 }
516
517                                 if (HasElementType)
518                                         return GetElementType ().ContainsGenericParameters;
519
520                                 return false;
521                         }
522                 }
523
524                 public extern override bool IsGenericParameter {
525                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
526                         get;
527                 }
528
529                 public extern override MethodInfo DeclaringMethod {
530                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
531                         get;
532                 }
533 #endif
534         }
535 }