Make TypeNameParser consistently use tabs
[mono-project.git] / netcore / System.Private.CoreLib / src / System / RuntimeType.cs
blob190a33317582e7f512d65d4d3dcff9150cb71229
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Reflection;
6 using System.Globalization;
7 using System.Threading;
8 using System.Collections.Generic;
9 using System.Runtime.Serialization;
10 using System.Runtime.CompilerServices;
11 using System.Diagnostics.Contracts;
12 using System.Runtime.InteropServices;
13 using System.Diagnostics;
15 namespace System
17 // Keep this in sync with FormatFlags defined in typestring.h
18 internal enum TypeNameFormatFlags
20 FormatBasic = 0x00000000, // Not a bitmask, simply the tersest flag settings possible
21 FormatNamespace = 0x00000001, // Include namespace and/or enclosing class names in type names
22 FormatFullInst = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings)
23 FormatAssembly = 0x00000004, // Include assembly display name in type names
24 FormatSignature = 0x00000008, // Include signature in method names
25 FormatNoVersion = 0x00000010, // Suppress version and culture information in all assembly names
26 #if _DEBUG
27 FormatDebug = 0x00000020, // For debug printing of types only
28 #endif
29 FormatAngleBrackets = 0x00000040, // Whether generic types are C<T> or C[T]
30 FormatStubInfo = 0x00000080, // Include stub info like {unbox-stub}
31 FormatGenericParam = 0x00000100, // Use !name and !!name for generic type and method parameters
33 // If we want to be able to distinguish between overloads whose parameter types have the same name but come from different assemblies,
34 // we can add FormatAssembly | FormatNoVersion to FormatSerialization. But we are omitting it because it is not a useful scenario
35 // and including the assembly name will normally increase the size of the serialized data and also decrease the performance.
36 FormatSerialization = FormatNamespace |
37 FormatGenericParam |
38 FormatFullInst
41 internal enum TypeNameKind
43 Name,
44 ToString,
45 SerializationName,
46 FullName,
49 partial class RuntimeType
51 #region Definitions
53 internal enum MemberListType
55 All,
56 CaseSensitive,
57 CaseInsensitive,
58 HandleToInfo
61 // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element.
62 private struct ListBuilder<T> where T : class
64 T[] _items;
65 T _item;
66 int _count;
67 int _capacity;
69 public ListBuilder(int capacity)
71 _items = null;
72 _item = null;
73 _count = 0;
74 _capacity = capacity;
77 public T this[int index]
79 get
81 Contract.Requires(index < Count);
82 return (_items != null) ? _items[index] : _item;
86 public T[] ToArray()
88 if (_count == 0)
89 return Array.Empty<T> ();
90 if (_count == 1)
91 return new T[1] { _item };
93 Array.Resize(ref _items, _count);
94 _capacity = _count;
95 return _items;
98 public void CopyTo(Object[] array, int index)
100 if (_count == 0)
101 return;
103 if (_count == 1)
105 array[index] = _item;
106 return;
109 Array.Copy(_items, 0, array, index, _count);
112 public int Count
116 return _count;
120 public void Add(T item)
122 if (_count == 0)
124 _item = item;
126 else
128 if (_count == 1)
130 if (_capacity < 2)
131 _capacity = 4;
132 _items = new T[_capacity];
133 _items[0] = _item;
135 else
136 if (_capacity == _count)
138 int newCapacity = 2 * _capacity;
139 Array.Resize(ref _items, newCapacity);
140 _capacity = newCapacity;
143 _items[_count] = item;
145 _count++;
149 #endregion
151 #region Static Members
153 #region Internal
155 internal static RuntimeType GetType(String typeName, bool throwOnError, bool ignoreCase, bool reflectionOnly,
156 ref StackCrawlMark stackMark)
158 if (typeName == null)
159 throw new ArgumentNullException("typeName");
160 Contract.EndContractBlock();
162 return RuntimeTypeHandle.GetTypeByName(
163 typeName, throwOnError, ignoreCase, reflectionOnly, ref stackMark, false);
166 private static void ThrowIfTypeNeverValidGenericArgument(RuntimeType type)
168 if (type.IsPointer || type.IsByRef || type == typeof(void))
169 throw new ArgumentException(
170 Environment.GetResourceString("Argument_NeverValidGenericArgument", type.ToString()));
173 internal static void SanityCheckGenericArguments(RuntimeType[] genericArguments, RuntimeType[] genericParamters)
175 if (genericArguments == null)
176 throw new ArgumentNullException();
177 Contract.EndContractBlock();
179 for(int i = 0; i < genericArguments.Length; i++)
181 if (genericArguments[i] == null)
182 throw new ArgumentNullException();
184 ThrowIfTypeNeverValidGenericArgument(genericArguments[i]);
187 if (genericArguments.Length != genericParamters.Length)
188 throw new ArgumentException(
189 Environment.GetResourceString("Argument_NotEnoughGenArguments", genericArguments.Length, genericParamters.Length));
192 private static void SplitName(string fullname, out string name, out string ns)
194 name = null;
195 ns = null;
197 if (fullname == null)
198 return;
200 // Get namespace
201 int nsDelimiter = fullname.LastIndexOf(".", StringComparison.Ordinal);
202 if (nsDelimiter != -1 )
204 ns = fullname.Substring(0, nsDelimiter);
205 int nameLength = fullname.Length - ns.Length - 1;
206 if (nameLength != 0)
207 name = fullname.Substring(nsDelimiter + 1, nameLength);
208 else
209 name = "";
210 Contract.Assert(fullname.Equals(ns + "." + name));
212 else
214 name = fullname;
218 #endregion
220 #region Filters
221 internal static BindingFlags FilterPreCalculate(bool isPublic, bool isInherited, bool isStatic)
223 BindingFlags bindingFlags = isPublic ? BindingFlags.Public : BindingFlags.NonPublic;
225 if (isInherited)
227 // We arrange things so the DeclaredOnly flag means "include inherited members"
228 bindingFlags |= BindingFlags.DeclaredOnly;
230 if (isStatic)
232 bindingFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
234 else
236 bindingFlags |= BindingFlags.Instance;
239 else
241 if (isStatic)
243 bindingFlags |= BindingFlags.Static;
245 else
247 bindingFlags |= BindingFlags.Instance;
251 return bindingFlags;
254 // Calculate prefixLookup, ignoreCase, and listType for use by GetXXXCandidates
255 private static void FilterHelper(
256 BindingFlags bindingFlags, ref string name, bool allowPrefixLookup, out bool prefixLookup,
257 out bool ignoreCase, out MemberListType listType)
259 prefixLookup = false;
260 ignoreCase = false;
262 if (name != null)
264 if ((bindingFlags & BindingFlags.IgnoreCase) != 0)
266 name = name.ToLower(CultureInfo.InvariantCulture);
267 ignoreCase = true;
268 listType = MemberListType.CaseInsensitive;
270 else
272 listType = MemberListType.CaseSensitive;
275 if (allowPrefixLookup && name.EndsWith("*", StringComparison.Ordinal))
277 // We set prefixLookup to true if name ends with a "*".
278 // We will also set listType to All so that all members are included in
279 // the candidates which are later filtered by FilterApplyPrefixLookup.
280 name = name.Substring(0, name.Length - 1);
281 prefixLookup = true;
282 listType = MemberListType.All;
285 else
287 listType = MemberListType.All;
291 // Used by the singular GetXXX APIs (Event, Field, Interface, NestedType) where prefixLookup is not supported.
292 private static void FilterHelper(BindingFlags bindingFlags, ref string name, out bool ignoreCase, out MemberListType listType)
294 bool prefixLookup;
295 FilterHelper(bindingFlags, ref name, false, out prefixLookup, out ignoreCase, out listType);
298 // Only called by GetXXXCandidates, GetInterfaces, and GetNestedTypes when FilterHelper has set "prefixLookup" to true.
299 // Most of the plural GetXXX methods allow prefix lookups while the singular GetXXX methods mostly do not.
300 private static bool FilterApplyPrefixLookup(MemberInfo memberInfo, string name, bool ignoreCase)
302 Contract.Assert(name != null);
304 if (ignoreCase)
306 if (!memberInfo.Name.StartsWith(name, StringComparison.OrdinalIgnoreCase))
307 return false;
309 else
311 if (!memberInfo.Name.StartsWith(name, StringComparison.Ordinal))
312 return false;
315 return true;
319 // Used by FilterApplyType to perform all the filtering based on name and BindingFlags
320 private static bool FilterApplyBase(
321 MemberInfo memberInfo, BindingFlags bindingFlags, bool isPublic, bool isNonProtectedInternal, bool isStatic,
322 string name, bool prefixLookup)
324 #region Preconditions
325 Contract.Requires(memberInfo != null);
326 Contract.Requires(name == null || (bindingFlags & BindingFlags.IgnoreCase) == 0 || (name.ToLower(CultureInfo.InvariantCulture).Equals(name)));
327 #endregion
329 #region Filter by Public & Private
330 if (isPublic)
332 if ((bindingFlags & BindingFlags.Public) == 0)
333 return false;
335 else
337 if ((bindingFlags & BindingFlags.NonPublic) == 0)
338 return false;
340 #endregion
342 bool isInherited = !Object.ReferenceEquals(memberInfo.DeclaringType, memberInfo.ReflectedType);
344 #region Filter by DeclaredOnly
345 if ((bindingFlags & BindingFlags.DeclaredOnly) != 0 && isInherited)
346 return false;
347 #endregion
349 #region Filter by Static & Instance
350 if (memberInfo.MemberType != MemberTypes.TypeInfo &&
351 memberInfo.MemberType != MemberTypes.NestedType)
353 if (isStatic)
355 if ((bindingFlags & BindingFlags.FlattenHierarchy) == 0 && isInherited)
356 return false;
358 if ((bindingFlags & BindingFlags.Static) == 0)
359 return false;
361 else
363 if ((bindingFlags & BindingFlags.Instance) == 0)
364 return false;
367 #endregion
369 #region Filter by name wrt prefixLookup and implicitly by case sensitivity
370 if (prefixLookup == true)
372 if (!FilterApplyPrefixLookup(memberInfo, name, (bindingFlags & BindingFlags.IgnoreCase) != 0))
373 return false;
375 #endregion
377 #region Asymmetries
378 // @Asymmetry - Internal, inherited, instance, non-protected, non-virtual, non-abstract members returned
379 // iff BindingFlags !DeclaredOnly, Instance and Public are present except for fields
380 if (((bindingFlags & BindingFlags.DeclaredOnly) == 0) && // DeclaredOnly not present
381 isInherited && // Is inherited Member
383 (isNonProtectedInternal) && // Is non-protected internal member
384 ((bindingFlags & BindingFlags.NonPublic) != 0) && // BindingFlag.NonPublic present
386 (!isStatic) && // Is instance member
387 ((bindingFlags & BindingFlags.Instance) != 0)) // BindingFlag.Instance present
389 MethodInfo methodInfo = memberInfo as MethodInfo;
391 if (methodInfo == null)
392 return false;
394 if (!methodInfo.IsVirtual && !methodInfo.IsAbstract)
395 return false;
397 #endregion
399 return true;
403 // Used by GetInterface and GetNestedType(s) which don't need parameter type filtering.
404 private static bool FilterApplyType(
405 Type type, BindingFlags bindingFlags, string name, bool prefixLookup, string ns)
407 Contract.Requires((object)type != null);
408 Contract.Assert(type is RuntimeType);
410 bool isPublic = type.IsNestedPublic || type.IsPublic;
411 bool isStatic = false;
413 if (!FilterApplyBase(type, bindingFlags, isPublic, type.IsNestedAssembly, isStatic, name, prefixLookup))
414 return false;
416 if (ns != null && ns != type.Namespace)
417 return false;
419 return true;
423 private static bool FilterApplyMethodInfo(
424 RuntimeMethodInfo method, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
426 // Optimization: Pre-Calculate the method binding flags to avoid casting.
427 return FilterApplyMethodBase(method, method.BindingFlags, bindingFlags, callConv, argumentTypes);
430 private static bool FilterApplyConstructorInfo(
431 RuntimeConstructorInfo constructor, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
433 // Optimization: Pre-Calculate the method binding flags to avoid casting.
434 return FilterApplyMethodBase(constructor, constructor.BindingFlags, bindingFlags, callConv, argumentTypes);
437 // Used by GetMethodCandidates/GetConstructorCandidates, InvokeMember, and CreateInstanceImpl to perform the necessary filtering.
438 // Should only be called by FilterApplyMethodInfo and FilterApplyConstructorInfo.
439 private static bool FilterApplyMethodBase(
440 MethodBase methodBase, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
442 Contract.Requires(methodBase != null);
444 bindingFlags ^= BindingFlags.DeclaredOnly;
445 #region Check CallingConvention
446 if ((callConv & CallingConventions.Any) == 0)
448 if ((callConv & CallingConventions.VarArgs) != 0 &&
449 (methodBase.CallingConvention & CallingConventions.VarArgs) == 0)
450 return false;
452 if ((callConv & CallingConventions.Standard) != 0 &&
453 (methodBase.CallingConvention & CallingConventions.Standard) == 0)
454 return false;
456 #endregion
458 #region If argumentTypes supplied
459 if (argumentTypes != null)
461 ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy();
463 if (argumentTypes.Length != parameterInfos.Length)
465 #region Invoke Member, Get\Set & Create Instance specific case
466 // If the number of supplied arguments differs than the number in the signature AND
467 // we are not filtering for a dynamic call -- InvokeMethod or CreateInstance -- filter out the method.
468 if ((bindingFlags &
469 (BindingFlags.InvokeMethod | BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty)) == 0)
470 return false;
472 bool testForParamArray = false;
473 bool excessSuppliedArguments = argumentTypes.Length > parameterInfos.Length;
475 if (excessSuppliedArguments)
476 { // more supplied arguments than parameters, additional arguments could be vararg
477 #region Varargs
478 // If method is not vararg, additional arguments can not be passed as vararg
479 if ((methodBase.CallingConvention & CallingConventions.VarArgs) == 0)
481 testForParamArray = true;
483 else
485 // If Binding flags did not include varargs we would have filtered this vararg method.
486 // This Invariant established during callConv check.
487 Contract.Assert((callConv & CallingConventions.VarArgs) != 0);
489 #endregion
491 else
492 {// fewer supplied arguments than parameters, missing arguments could be optional
493 #region OptionalParamBinding
494 if ((bindingFlags & BindingFlags.OptionalParamBinding) == 0)
496 testForParamArray = true;
498 else
500 // From our existing code, our policy here is that if a parameterInfo
501 // is optional then all subsequent parameterInfos shall be optional.
503 // Thus, iff the first parameterInfo is not optional then this MethodInfo is no longer a canidate.
504 if (!parameterInfos[argumentTypes.Length].IsOptional)
505 testForParamArray = true;
507 #endregion
510 #region ParamArray
511 if (testForParamArray)
513 if (parameterInfos.Length == 0)
514 return false;
516 // The last argument of the signature could be a param array.
517 bool shortByMoreThanOneSuppliedArgument = argumentTypes.Length < parameterInfos.Length - 1;
519 if (shortByMoreThanOneSuppliedArgument)
520 return false;
522 ParameterInfo lastParameter = parameterInfos[parameterInfos.Length - 1];
524 if (!lastParameter.ParameterType.IsArray)
525 return false;
527 if (!lastParameter.IsDefined(typeof(ParamArrayAttribute), false))
528 return false;
530 #endregion
532 #endregion
534 else
536 #region Exact Binding
537 if ((bindingFlags & BindingFlags.ExactBinding) != 0)
539 // Legacy behavior is to ignore ExactBinding when InvokeMember is specified.
540 // Why filter by InvokeMember? If the answer is we leave this to the binder then why not leave
541 // all the rest of this to the binder too? Further, what other semanitc would the binder
542 // use for BindingFlags.ExactBinding besides this one? Further, why not include CreateInstance
543 // in this if statement? That's just InvokeMethod with a constructor, right?
544 if ((bindingFlags & (BindingFlags.InvokeMethod)) == 0)
546 for(int i = 0; i < parameterInfos.Length; i ++)
548 // a null argument type implies a null arg which is always a perfect match
549 if ((object)argumentTypes[i] != null && !argumentTypes[i].MatchesParameterTypeExactly(parameterInfos[i]))
550 return false;
554 #endregion
557 #endregion
559 return true;
562 #endregion
564 #endregion
566 #region Private Data Members
568 internal static readonly RuntimeType ValueType = (RuntimeType)typeof(System.ValueType);
569 internal static readonly RuntimeType EnumType = (RuntimeType)typeof(System.Enum);
571 private static readonly RuntimeType ObjectType = (RuntimeType)typeof(System.Object);
572 private static readonly RuntimeType StringType = (RuntimeType)typeof(System.String);
573 private static readonly RuntimeType DelegateType = (RuntimeType)typeof(System.Delegate);
575 #endregion
577 #region Constructor
578 internal RuntimeType() { throw new NotSupportedException(); }
579 #endregion
581 #region Type Overrides
583 #region Get XXXInfo Candidates
584 private ListBuilder<MethodInfo> GetMethodCandidates(
585 String name, BindingFlags bindingAttr, CallingConventions callConv,
586 Type[] types, int genericParamCount, bool allowPrefixLookup)
588 bool prefixLookup, ignoreCase;
589 MemberListType listType;
590 FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
592 RuntimeMethodInfo[] cache = GetMethodsByName (name, bindingAttr, listType, this);
593 ListBuilder<MethodInfo> candidates = new ListBuilder<MethodInfo>(cache.Length);
595 for (int i = 0; i < cache.Length; i++)
597 RuntimeMethodInfo methodInfo = cache[i];
598 if (genericParamCount != -1) {
599 bool is_generic = methodInfo.IsGenericMethod;
600 if (genericParamCount == 0 && is_generic)
601 continue;
602 else if (genericParamCount > 0 && !is_generic)
603 continue;
604 var args = methodInfo.GetGenericArguments ();
605 if (args.Length != genericParamCount)
606 continue;
608 if (FilterApplyMethodInfo(methodInfo, bindingAttr, callConv, types) &&
609 (!prefixLookup || FilterApplyPrefixLookup(methodInfo, name, ignoreCase)))
611 candidates.Add(methodInfo);
615 return candidates;
618 private ListBuilder<ConstructorInfo> GetConstructorCandidates(
619 string name, BindingFlags bindingAttr, CallingConventions callConv,
620 Type[] types, bool allowPrefixLookup)
622 bool prefixLookup, ignoreCase;
623 MemberListType listType;
624 FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
626 if (!string.IsNullOrEmpty (name) && name != ConstructorInfo.ConstructorName && name != ConstructorInfo.TypeConstructorName)
627 return new ListBuilder<ConstructorInfo> (0);
628 RuntimeConstructorInfo[] cache = GetConstructors_internal (bindingAttr, this);
629 ListBuilder<ConstructorInfo> candidates = new ListBuilder<ConstructorInfo>(cache.Length);
630 for (int i = 0; i < cache.Length; i++)
632 RuntimeConstructorInfo constructorInfo = cache[i];
633 if (FilterApplyConstructorInfo(constructorInfo, bindingAttr, callConv, types) &&
634 (!prefixLookup || FilterApplyPrefixLookup(constructorInfo, name, ignoreCase)))
636 candidates.Add(constructorInfo);
640 return candidates;
644 private ListBuilder<PropertyInfo> GetPropertyCandidates(
645 String name, BindingFlags bindingAttr, Type[] types, bool allowPrefixLookup)
647 bool prefixLookup, ignoreCase;
648 MemberListType listType;
649 FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
651 RuntimePropertyInfo[] cache = GetPropertiesByName (name, bindingAttr, listType, this);
652 bindingAttr ^= BindingFlags.DeclaredOnly;
654 ListBuilder<PropertyInfo> candidates = new ListBuilder<PropertyInfo>(cache.Length);
655 for (int i = 0; i < cache.Length; i++)
657 RuntimePropertyInfo propertyInfo = cache[i];
658 if ((bindingAttr & propertyInfo.BindingFlags) == propertyInfo.BindingFlags &&
659 (!prefixLookup || FilterApplyPrefixLookup(propertyInfo, name, ignoreCase)) &&
660 (types == null || (propertyInfo.GetIndexParameters().Length == types.Length)))
662 candidates.Add(propertyInfo);
666 return candidates;
669 private ListBuilder<EventInfo> GetEventCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup)
671 bool prefixLookup, ignoreCase;
672 MemberListType listType;
673 FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
675 RuntimeEventInfo[] cache = GetEvents_internal (name, bindingAttr, listType, this);
676 bindingAttr ^= BindingFlags.DeclaredOnly;
678 ListBuilder<EventInfo> candidates = new ListBuilder<EventInfo>(cache.Length);
679 for (int i = 0; i < cache.Length; i++)
681 RuntimeEventInfo eventInfo = cache[i];
682 if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags &&
683 (!prefixLookup || FilterApplyPrefixLookup(eventInfo, name, ignoreCase)))
685 candidates.Add(eventInfo);
689 return candidates;
692 private ListBuilder<FieldInfo> GetFieldCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup)
694 bool prefixLookup, ignoreCase;
695 MemberListType listType;
696 FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
698 RuntimeFieldInfo[] cache = GetFields_internal (name, bindingAttr, listType, this);
699 bindingAttr ^= BindingFlags.DeclaredOnly;
701 ListBuilder<FieldInfo> candidates = new ListBuilder<FieldInfo>(cache.Length);
702 for (int i = 0; i < cache.Length; i++)
704 RuntimeFieldInfo fieldInfo = cache[i];
705 if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags &&
706 (!prefixLookup || FilterApplyPrefixLookup(fieldInfo, name, ignoreCase)))
708 candidates.Add(fieldInfo);
712 return candidates;
715 private ListBuilder<Type> GetNestedTypeCandidates(String fullname, BindingFlags bindingAttr, bool allowPrefixLookup)
717 bool prefixLookup, ignoreCase;
718 bindingAttr &= ~BindingFlags.Static;
719 string name, ns;
720 MemberListType listType;
721 SplitName(fullname, out name, out ns);
722 FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
724 RuntimeType[] cache = GetNestedTypes_internal (name, bindingAttr, listType);
725 ListBuilder<Type> candidates = new ListBuilder<Type>(cache.Length);
726 for (int i = 0; i < cache.Length; i++)
728 RuntimeType nestedClass = cache[i];
729 if (FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, ns))
731 candidates.Add(nestedClass);
735 return candidates;
738 #endregion
740 #region Get All XXXInfos
741 public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
743 return GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, -1, false).ToArray();
746 [ComVisible(true)]
747 public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
749 return GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false).ToArray();
752 public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
754 return GetPropertyCandidates(null, bindingAttr, null, false).ToArray();
757 public override EventInfo[] GetEvents(BindingFlags bindingAttr)
759 return GetEventCandidates(null, bindingAttr, false).ToArray();
762 public override FieldInfo[] GetFields(BindingFlags bindingAttr)
764 return GetFieldCandidates(null, bindingAttr, false).ToArray();
767 public override Type[] GetNestedTypes(BindingFlags bindingAttr)
769 return GetNestedTypeCandidates(null, bindingAttr, false).ToArray();
772 public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
774 ListBuilder<MethodInfo> methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, -1, false);
775 ListBuilder<ConstructorInfo> constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false);
776 ListBuilder<PropertyInfo> properties = GetPropertyCandidates(null, bindingAttr, null, false);
777 ListBuilder<EventInfo> events = GetEventCandidates(null, bindingAttr, false);
778 ListBuilder<FieldInfo> fields = GetFieldCandidates(null, bindingAttr, false);
779 ListBuilder<Type> nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false);
780 // Interfaces are excluded from the result of GetMembers
782 MemberInfo[] members = new MemberInfo[
783 methods.Count +
784 constructors.Count +
785 properties.Count +
786 events.Count +
787 fields.Count +
788 nestedTypes.Count];
790 int i = 0;
791 methods.CopyTo(members, i); i += methods.Count;
792 constructors.CopyTo(members, i); i += constructors.Count;
793 properties.CopyTo(members, i); i += properties.Count;
794 events.CopyTo(members, i); i += events.Count;
795 fields.CopyTo(members, i); i += fields.Count;
796 nestedTypes.CopyTo(members, i); i += nestedTypes.Count;
797 Contract.Assert(i == members.Length);
799 return members;
802 #endregion
804 protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
806 return GetMethodImpl (name, -1, bindingAttr, binder, callConvention, types, modifiers);
809 protected override MethodInfo GetMethodImpl(String name, int genericParamCount,
810 BindingFlags bindingAttr, Binder? binder, CallingConventions callConv,
811 Type[]? types, ParameterModifier[]? modifiers)
813 ListBuilder<MethodInfo> candidates = GetMethodCandidates(name, bindingAttr, callConv, types, genericParamCount, false);
814 if (candidates.Count == 0)
815 return null;
817 if (types == null || types.Length == 0)
819 MethodInfo firstCandidate = candidates[0];
821 if (candidates.Count == 1)
823 return firstCandidate;
825 else if (types == null)
827 for (int j = 1; j < candidates.Count; j++)
829 MethodInfo methodInfo = candidates[j];
830 if (!System.DefaultBinder.CompareMethodSig (methodInfo, firstCandidate))
831 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
834 // All the methods have the exact same name and sig so return the most derived one.
835 return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo;
839 if (binder == null)
840 binder = DefaultBinder;
842 return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as MethodInfo;
845 protected override ConstructorInfo GetConstructorImpl(
846 BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention,
847 Type[] types, ParameterModifier[]? modifiers)
849 ListBuilder<ConstructorInfo> candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false);
851 if (candidates.Count == 0)
852 return null;
854 if (types.Length == 0 && candidates.Count == 1)
856 ConstructorInfo firstCandidate = candidates[0];
858 ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy();
859 if (parameters == null || parameters.Length == 0)
861 return firstCandidate;
865 if ((bindingAttr & BindingFlags.ExactBinding) != 0)
866 return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers) as ConstructorInfo;
868 if (binder == null)
869 binder = DefaultBinder;
871 return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as ConstructorInfo;
875 protected override PropertyInfo GetPropertyImpl(
876 String name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers)
878 if (name == null) throw new ArgumentNullException();
879 Contract.EndContractBlock();
881 ListBuilder<PropertyInfo> candidates = GetPropertyCandidates(name, bindingAttr, types, false);
883 if (candidates.Count == 0)
884 return null;
886 if (types == null || types.Length == 0)
888 // no arguments
889 if (candidates.Count == 1)
891 PropertyInfo firstCandidate = candidates[0];
893 if ((object)returnType != null && !returnType.IsEquivalentTo(firstCandidate.PropertyType))
894 return null;
896 return firstCandidate;
898 else
900 if ((object)returnType == null)
901 // if we are here we have no args or property type to select over and we have more than one property with that name
902 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
906 if ((bindingAttr & BindingFlags.ExactBinding) != 0)
907 return System.DefaultBinder.ExactPropertyBinding(candidates.ToArray(), returnType, types, modifiers);
909 if (binder == null)
910 binder = DefaultBinder;
912 return binder.SelectProperty(bindingAttr, candidates.ToArray(), returnType, types, modifiers);
915 public override EventInfo GetEvent(String name, BindingFlags bindingAttr)
917 if (name == null) throw new ArgumentNullException();
918 Contract.EndContractBlock();
920 bool ignoreCase;
921 MemberListType listType;
922 FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
924 RuntimeEventInfo[] cache = GetEvents_internal (name, bindingAttr, listType, this);
925 EventInfo match = null;
927 bindingAttr ^= BindingFlags.DeclaredOnly;
929 for (int i = 0; i < cache.Length; i++)
931 RuntimeEventInfo eventInfo = cache[i];
932 if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags)
934 if (match != null)
935 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
937 match = eventInfo;
941 return match;
944 public override FieldInfo GetField(String name, BindingFlags bindingAttr)
946 if (name == null) throw new ArgumentNullException();
947 Contract.EndContractBlock();
949 bool ignoreCase;
950 MemberListType listType;
951 FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
953 RuntimeFieldInfo[] cache = GetFields_internal (name, bindingAttr, listType, this);
954 FieldInfo match = null;
956 bindingAttr ^= BindingFlags.DeclaredOnly;
957 bool multipleStaticFieldMatches = false;
959 for (int i = 0; i < cache.Length; i++)
961 RuntimeFieldInfo fieldInfo = cache[i];
962 if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags)
964 if (match != null)
966 if (Object.ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType))
967 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
969 if ((match.DeclaringType.IsInterface == true) && (fieldInfo.DeclaringType.IsInterface == true))
970 multipleStaticFieldMatches = true;
973 if (match == null || fieldInfo.DeclaringType.IsSubclassOf(match.DeclaringType) || match.DeclaringType.IsInterface)
974 match = fieldInfo;
978 if (multipleStaticFieldMatches && match.DeclaringType.IsInterface)
979 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
981 return match;
984 public override Type GetInterface(String fullname, bool ignoreCase)
986 if (fullname == null) throw new ArgumentNullException();
987 Contract.EndContractBlock();
989 BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic;
991 bindingAttr &= ~BindingFlags.Static;
993 if (ignoreCase)
994 bindingAttr |= BindingFlags.IgnoreCase;
996 string name, ns;
997 MemberListType listType;
998 SplitName(fullname, out name, out ns);
999 FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
1001 List<RuntimeType> list = null;
1002 var nameComparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
1003 foreach (RuntimeType t in GetInterfaces ()) {
1005 if (!String.Equals(t.Name, name, nameComparison)) {
1006 continue;
1009 if (list == null)
1010 list = new List<RuntimeType> (2);
1012 list.Add (t);
1015 if (list == null)
1016 return null;
1018 var cache = list.ToArray ();
1019 RuntimeType match = null;
1021 for (int i = 0; i < cache.Length; i++)
1023 RuntimeType iface = cache[i];
1024 if (FilterApplyType(iface, bindingAttr, name, false, ns))
1026 if (match != null)
1027 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
1029 match = iface;
1033 return match;
1036 public override Type GetNestedType(String fullname, BindingFlags bindingAttr)
1038 if (fullname == null) throw new ArgumentNullException();
1039 Contract.EndContractBlock();
1041 bool ignoreCase;
1042 bindingAttr &= ~BindingFlags.Static;
1043 string name, ns;
1044 MemberListType listType;
1045 SplitName(fullname, out name, out ns);
1046 FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
1047 RuntimeType[] cache = GetNestedTypes_internal (name, bindingAttr, listType);
1048 RuntimeType match = null;
1050 for (int i = 0; i < cache.Length; i++)
1052 RuntimeType nestedType = cache[i];
1053 if (FilterApplyType(nestedType, bindingAttr, name, false, ns))
1055 if (match != null)
1056 throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
1058 match = nestedType;
1062 return match;
1065 public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
1067 if (name == null) throw new ArgumentNullException();
1068 Contract.EndContractBlock();
1070 ListBuilder<MethodInfo> methods = new ListBuilder<MethodInfo>();
1071 ListBuilder<ConstructorInfo> constructors = new ListBuilder<ConstructorInfo>();
1072 ListBuilder<PropertyInfo> properties = new ListBuilder<PropertyInfo>();
1073 ListBuilder<EventInfo> events = new ListBuilder<EventInfo>();
1074 ListBuilder<FieldInfo> fields = new ListBuilder<FieldInfo>();
1075 ListBuilder<Type> nestedTypes = new ListBuilder<Type>();
1077 int totalCount = 0;
1079 // Methods
1080 if ((type & MemberTypes.Method) != 0)
1082 methods = GetMethodCandidates(name, bindingAttr, CallingConventions.Any, null, -1, true);
1083 if (type == MemberTypes.Method)
1084 return methods.ToArray();
1085 totalCount += methods.Count;
1088 // Constructors
1089 if ((type & MemberTypes.Constructor) != 0)
1091 constructors = GetConstructorCandidates(name, bindingAttr, CallingConventions.Any, null, true);
1092 if (type == MemberTypes.Constructor)
1093 return constructors.ToArray();
1094 totalCount += constructors.Count;
1097 // Properties
1098 if ((type & MemberTypes.Property) != 0)
1100 properties = GetPropertyCandidates(name, bindingAttr, null, true);
1101 if (type == MemberTypes.Property)
1102 return properties.ToArray();
1103 totalCount += properties.Count;
1106 // Events
1107 if ((type & MemberTypes.Event) != 0)
1109 events = GetEventCandidates(name, bindingAttr, true);
1110 if (type == MemberTypes.Event)
1111 return events.ToArray();
1112 totalCount += events.Count;
1115 // Fields
1116 if ((type & MemberTypes.Field) != 0)
1118 fields = GetFieldCandidates(name, bindingAttr, true);
1119 if (type == MemberTypes.Field)
1120 return fields.ToArray();
1121 totalCount += fields.Count;
1124 // NestedTypes
1125 if ((type & (MemberTypes.NestedType | MemberTypes.TypeInfo)) != 0)
1127 nestedTypes = GetNestedTypeCandidates(name, bindingAttr, true);
1128 if (type == MemberTypes.NestedType || type == MemberTypes.TypeInfo)
1129 return nestedTypes.ToArray();
1130 totalCount += nestedTypes.Count;
1133 MemberInfo[] compressMembers = (type == (MemberTypes.Method | MemberTypes.Constructor)) ?
1134 new MethodBase[totalCount] : new MemberInfo[totalCount];
1136 int i = 0;
1137 methods.CopyTo(compressMembers, i); i += methods.Count;
1138 constructors.CopyTo(compressMembers, i); i += constructors.Count;
1139 properties.CopyTo(compressMembers, i); i += properties.Count;
1140 events.CopyTo(compressMembers, i); i += events.Count;
1141 fields.CopyTo(compressMembers, i); i += fields.Count;
1142 nestedTypes.CopyTo(compressMembers, i); i += nestedTypes.Count;
1143 Contract.Assert(i == compressMembers.Length);
1145 return compressMembers;
1147 #endregion
1150 #region Hierarchy
1152 // Reflexive, symmetric, transitive.
1153 public override bool IsEquivalentTo(Type? other)
1155 RuntimeType otherRtType = other as RuntimeType;
1156 if ((object)otherRtType == null)
1157 return false;
1159 if (otherRtType == this)
1160 return true;
1162 // It's not worth trying to perform further checks in managed
1163 // as they would lead to FCalls anyway.
1164 return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType);
1167 #endregion
1169 #region Attributes
1171 internal bool IsDelegate()
1173 return GetBaseType() == typeof(System.MulticastDelegate);
1176 public override bool IsEnum => GetBaseType() == EnumType;
1178 public override GenericParameterAttributes GenericParameterAttributes
1182 if (!IsGenericParameter)
1183 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
1184 Contract.EndContractBlock();
1186 return GetGenericParameterAttributes ();
1190 #endregion
1192 #region Generics
1194 internal RuntimeType[] GetGenericArgumentsInternal()
1196 return (RuntimeType[]) GetGenericArgumentsInternal (true);
1199 public override Type[] GetGenericArguments()
1201 Type[] types = GetGenericArgumentsInternal (false);
1203 if (types == null)
1204 types = Array.Empty<Type> ();
1206 return types;
1209 public override Type MakeGenericType(Type[] instantiation)
1211 if (instantiation == null)
1212 throw new ArgumentNullException("instantiation");
1213 Contract.EndContractBlock();
1215 RuntimeType[] instantiationRuntimeType = new RuntimeType[instantiation.Length];
1217 if (!IsGenericTypeDefinition)
1218 throw new InvalidOperationException(
1219 Environment.GetResourceString("Arg_NotGenericTypeDefinition", this));
1221 if (GetGenericArguments().Length != instantiation.Length)
1222 throw new ArgumentException(Environment.GetResourceString("Argument_GenericArgsCount"), "instantiation");
1224 for (int i = 0; i < instantiation.Length; i ++)
1226 Type instantiationElem = instantiation[i];
1227 if (instantiationElem == null)
1228 throw new ArgumentNullException();
1230 RuntimeType rtInstantiationElem = instantiationElem as RuntimeType;
1232 if (rtInstantiationElem == null)
1234 if (instantiationElem.IsSignatureType)
1235 return MakeGenericSignatureType (this, instantiation);
1236 Type[] instantiationCopy = new Type[instantiation.Length];
1237 for (int iCopy = 0; iCopy < instantiation.Length; iCopy++)
1238 instantiationCopy[iCopy] = instantiation[iCopy];
1239 instantiation = instantiationCopy;
1241 throw new NotImplementedException ();
1244 instantiationRuntimeType[i] = rtInstantiationElem;
1247 RuntimeType[] genericParameters = GetGenericArgumentsInternal();
1249 SanityCheckGenericArguments(instantiationRuntimeType, genericParameters);
1251 Type ret = null;
1252 ret = MakeGenericType (this, instantiationRuntimeType);
1253 if (ret == null)
1254 throw new TypeLoadException ();
1255 return ret;
1258 public override int GenericParameterPosition
1260 get
1262 if (!IsGenericParameter)
1263 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
1264 Contract.EndContractBlock();
1265 return GetGenericParameterPosition ();
1269 #endregion
1271 #region Invoke Member
1272 private const BindingFlags MemberBindingMask = (BindingFlags)0x000000FF;
1273 private const BindingFlags InvocationMask = (BindingFlags)0x0000FF00;
1274 private const BindingFlags BinderNonCreateInstance = BindingFlags.InvokeMethod | BinderGetSetField | BinderGetSetProperty;
1275 private const BindingFlags BinderGetSetProperty = BindingFlags.GetProperty | BindingFlags.SetProperty;
1276 private const BindingFlags BinderSetInvokeProperty = BindingFlags.InvokeMethod | BindingFlags.SetProperty;
1277 private const BindingFlags BinderGetSetField = BindingFlags.GetField | BindingFlags.SetField;
1278 private const BindingFlags BinderSetInvokeField = BindingFlags.SetField | BindingFlags.InvokeMethod;
1279 private const BindingFlags BinderNonFieldGetSet = (BindingFlags)0x00FFF300;
1280 private const BindingFlags ClassicBindingMask =
1281 BindingFlags.InvokeMethod | BindingFlags.GetProperty | BindingFlags.SetProperty |
1282 BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty;
1283 private static RuntimeType s_typedRef = (RuntimeType)typeof(TypedReference);
1286 [DebuggerStepThroughAttribute]
1287 [Diagnostics.DebuggerHidden]
1288 public override Object InvokeMember(
1289 String name, BindingFlags bindingFlags, Binder? binder, Object? target,
1290 Object?[]? providedArgs, ParameterModifier[]? modifiers, CultureInfo? culture, String[]? namedParams)
1292 if (IsGenericParameter)
1293 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
1294 Contract.EndContractBlock();
1296 #region Preconditions
1297 if ((bindingFlags & InvocationMask) == 0)
1298 // "Must specify binding flags describing the invoke operation required."
1299 throw new ArgumentException(Environment.GetResourceString("Arg_NoAccessSpec"),"bindingFlags");
1301 // Provide a default binding mask if none is provided
1302 if ((bindingFlags & MemberBindingMask) == 0)
1304 bindingFlags |= BindingFlags.Instance | BindingFlags.Public;
1306 if ((bindingFlags & BindingFlags.CreateInstance) == 0)
1307 bindingFlags |= BindingFlags.Static;
1310 // There must not be more named parameters than provided arguments
1311 if (namedParams != null)
1313 if (providedArgs != null)
1315 if (namedParams.Length > providedArgs.Length)
1316 // "Named parameter array can not be bigger than argument array."
1317 throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams");
1319 else
1321 if (namedParams.Length != 0)
1322 // "Named parameter array can not be bigger than argument array."
1323 throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams");
1326 #endregion
1328 #region Check that any named paramters are not null
1329 if (namedParams != null && Array.IndexOf(namedParams, null) != -1)
1330 // "Named parameter value must not be null."
1331 throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"),"namedParams");
1332 #endregion
1334 int argCnt = (providedArgs != null) ? providedArgs.Length : 0;
1336 #region Get a Binder
1337 if (binder == null)
1338 binder = DefaultBinder;
1340 #endregion
1342 #region Delegate to Activator.CreateInstance
1343 if ((bindingFlags & BindingFlags.CreateInstance) != 0)
1345 if ((bindingFlags & BindingFlags.CreateInstance) != 0 && (bindingFlags & BinderNonCreateInstance) != 0)
1346 // "Can not specify both CreateInstance and another access type."
1347 throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"),"bindingFlags");
1349 return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture);
1351 #endregion
1353 // PutDispProperty and\or PutRefDispProperty ==> SetProperty.
1354 if ((bindingFlags & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0)
1355 bindingFlags |= BindingFlags.SetProperty;
1357 #region Name
1358 if (name == null)
1359 throw new ArgumentNullException("name");
1361 if (name.Length == 0 || name.Equals(@"[DISPID=0]"))
1363 name = GetDefaultMemberName();
1365 if (name == null)
1367 // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString
1368 name = "ToString";
1371 #endregion
1373 #region GetField or SetField
1374 bool IsGetField = (bindingFlags & BindingFlags.GetField) != 0;
1375 bool IsSetField = (bindingFlags & BindingFlags.SetField) != 0;
1377 if (IsGetField || IsSetField)
1379 #region Preconditions
1380 if (IsGetField)
1382 if (IsSetField)
1383 // "Can not specify both Get and Set on a field."
1384 throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"),"bindingFlags");
1386 if ((bindingFlags & BindingFlags.SetProperty) != 0)
1387 // "Can not specify both GetField and SetProperty."
1388 throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),"bindingFlags");
1390 else
1392 Contract.Assert(IsSetField);
1394 if (providedArgs == null)
1395 throw new ArgumentNullException("providedArgs");
1397 if ((bindingFlags & BindingFlags.GetProperty) != 0)
1398 // "Can not specify both SetField and GetProperty."
1399 throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),"bindingFlags");
1401 if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
1402 // "Can not specify Set on a Field and Invoke on a method."
1403 throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"),"bindingFlags");
1405 #endregion
1407 #region Lookup Field
1408 FieldInfo selFld = null;
1409 FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[];
1411 Contract.Assert(flds != null);
1413 if (flds.Length == 1)
1415 selFld = flds[0];
1417 else if (flds.Length > 0)
1419 selFld = binder.BindToField(bindingFlags, flds, IsGetField ? Empty.Value : providedArgs[0], culture);
1421 #endregion
1423 if (selFld != null)
1425 #region Invocation on a field
1426 if (selFld.FieldType.IsArray || Object.ReferenceEquals(selFld.FieldType, typeof(System.Array)))
1428 #region Invocation of an array Field
1429 int idxCnt;
1431 if ((bindingFlags & BindingFlags.GetField) != 0)
1433 idxCnt = argCnt;
1435 else
1437 idxCnt = argCnt - 1;
1440 if (idxCnt > 0)
1442 // Verify that all of the index values are ints
1443 int[] idx = new int[idxCnt];
1444 for (int i=0;i<idxCnt;i++)
1446 try
1448 idx[i] = ((IConvertible)providedArgs[i]).ToInt32(null);
1450 catch (InvalidCastException)
1452 throw new ArgumentException(Environment.GetResourceString("Arg_IndexMustBeInt"));
1456 // Set or get the value...
1457 Array a = (Array) selFld.GetValue(target);
1459 // Set or get the value in the array
1460 if ((bindingFlags & BindingFlags.GetField) != 0)
1462 return a.GetValue(idx);
1464 else
1466 a.SetValue(providedArgs[idxCnt],idx);
1467 return null;
1470 #endregion
1473 if (IsGetField)
1475 #region Get the field value
1476 if (argCnt != 0)
1477 throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"),"bindingFlags");
1479 return selFld.GetValue(target);
1480 #endregion
1482 else
1484 #region Set the field Value
1485 if (argCnt != 1)
1486 throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"),"bindingFlags");
1488 selFld.SetValue(target,providedArgs[0],bindingFlags,binder,culture);
1490 return null;
1491 #endregion
1493 #endregion
1496 if ((bindingFlags & BinderNonFieldGetSet) == 0)
1497 throw new MissingFieldException(FullName, name);
1499 #endregion
1501 #region Caching Logic
1503 bool useCache = false;
1505 // Note that when we add something to the cache, we are careful to ensure
1506 // that the actual providedArgs matches the parameters of the method. Otherwise,
1507 // some default argument processing has occurred. We don't want anyone
1508 // else with the same (insufficient) number of actual arguments to get a
1509 // cache hit because then they would bypass the default argument processing
1510 // and the invocation would fail.
1511 if (bDefaultBinder && namedParams == null && argCnt < 6)
1512 useCache = true;
1514 if (useCache)
1516 MethodBase invokeMethod = GetMethodFromCache (name, bindingFlags, argCnt, providedArgs);
1518 if (invokeMethod != null)
1519 return ((MethodInfo) invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
1522 #endregion
1524 #region Property PreConditions
1525 // @Legacy - This is RTM behavior
1526 bool isGetProperty = (bindingFlags & BindingFlags.GetProperty) != 0;
1527 bool isSetProperty = (bindingFlags & BindingFlags.SetProperty) != 0;
1529 if (isGetProperty || isSetProperty)
1531 #region Preconditions
1532 if (isGetProperty)
1534 Contract.Assert(!IsSetField);
1536 if (isSetProperty)
1537 throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags");
1539 else
1541 Contract.Assert(isSetProperty);
1543 Contract.Assert(!IsGetField);
1545 if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
1546 throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags");
1548 #endregion
1550 #endregion
1552 MethodInfo[] finalists = null;
1553 MethodInfo finalist = null;
1555 #region BindingFlags.InvokeMethod
1556 if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
1558 #region Lookup Methods
1559 MethodInfo[] semiFinalists = GetMember(name, MemberTypes.Method, bindingFlags) as MethodInfo[];
1560 List<MethodInfo> results = null;
1562 for(int i = 0; i < semiFinalists.Length; i ++)
1564 MethodInfo semiFinalist = semiFinalists[i];
1565 Contract.Assert(semiFinalist != null);
1567 if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
1568 continue;
1570 if (finalist == null)
1572 finalist = semiFinalist;
1574 else
1576 if (results == null)
1578 results = new List<MethodInfo>(semiFinalists.Length);
1579 results.Add(finalist);
1582 results.Add(semiFinalist);
1586 if (results != null)
1588 Contract.Assert(results.Count > 1);
1589 finalists = new MethodInfo[results.Count];
1590 results.CopyTo(finalists);
1592 #endregion
1594 #endregion
1596 Contract.Assert(finalists == null || finalist != null);
1598 #region BindingFlags.GetProperty or BindingFlags.SetProperty
1599 if (finalist == null && isGetProperty || isSetProperty)
1601 #region Lookup Property
1602 PropertyInfo[] semiFinalists = GetMember(name, MemberTypes.Property, bindingFlags) as PropertyInfo[];
1603 List<MethodInfo> results = null;
1605 for(int i = 0; i < semiFinalists.Length; i ++)
1607 MethodInfo semiFinalist = null;
1609 if (isSetProperty)
1611 semiFinalist = semiFinalists[i].GetSetMethod(true);
1613 else
1615 semiFinalist = semiFinalists[i].GetGetMethod(true);
1618 if (semiFinalist == null)
1619 continue;
1621 if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
1622 continue;
1624 if (finalist == null)
1626 finalist = semiFinalist;
1628 else
1630 if (results == null)
1632 results = new List<MethodInfo>(semiFinalists.Length);
1633 results.Add(finalist);
1636 results.Add(semiFinalist);
1640 if (results != null)
1642 Contract.Assert(results.Count > 1);
1643 finalists = new MethodInfo[results.Count];
1644 results.CopyTo(finalists);
1646 #endregion
1648 #endregion
1650 if (finalist != null)
1652 #region Invoke
1653 if (finalists == null &&
1654 argCnt == 0 &&
1655 finalist.GetParametersNoCopy().Length == 0 &&
1656 (bindingFlags & BindingFlags.OptionalParamBinding) == 0)
1658 //if (useCache && argCnt == props[0].GetParameters().Length)
1659 // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, props[0]);
1661 return finalist.Invoke(target, bindingFlags, binder, providedArgs, culture);
1664 if (finalists == null)
1665 finalists = new MethodInfo[] { finalist };
1667 if (providedArgs == null)
1668 providedArgs = Array.Empty<Object>();
1670 Object state = null;
1673 MethodBase invokeMethod = null;
1675 try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs, modifiers, culture, namedParams, out state); }
1676 catch(MissingMethodException) { }
1678 if (invokeMethod == null)
1679 throw new MissingMethodException(FullName, name);
1681 //if (useCache && argCnt == invokeMethod.GetParameters().Length)
1682 // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, invokeMethod);
1684 Object result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
1686 if (state != null)
1687 binder.ReorderArgumentArray(ref providedArgs, state);
1689 return result;
1690 #endregion
1693 throw new MissingMethodException(FullName, name);
1695 #endregion
1697 public static bool operator ==(RuntimeType left, RuntimeType right)
1699 return object.ReferenceEquals(left, right);
1702 public static bool operator !=(RuntimeType left, RuntimeType right)
1704 return !object.ReferenceEquals(left, right);
1707 #region Legacy Internal
1708 private void CreateInstanceCheckThis()
1710 if (ContainsGenericParameters)
1711 throw new ArgumentException(
1712 Environment.GetResourceString("Acc_CreateGenericEx", this));
1713 Contract.EndContractBlock();
1715 Type elementType = this.GetRootElementType();
1717 if (Object.ReferenceEquals(elementType, typeof(ArgIterator)))
1718 throw new NotSupportedException(Environment.GetResourceString("Acc_CreateArgIterator"));
1720 if (Object.ReferenceEquals(elementType, typeof(void)))
1721 throw new NotSupportedException(Environment.GetResourceString("Acc_CreateVoid"));
1724 internal Object CreateInstanceImpl(
1725 BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
1727 CreateInstanceCheckThis();
1729 Object server = null;
1735 if (args == null)
1736 args = Array.Empty<Object> ();
1738 int argCnt = args.Length;
1740 // Without a binder we need to do use the default binder...
1741 if (binder == null)
1742 binder = DefaultBinder;
1744 // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors
1745 // so a call to GetMemberCons would fail
1746 bool publicOnly = (bindingAttr & BindingFlags.NonPublic) == 0;
1747 bool wrapExceptions = (bindingAttr & BindingFlags.DoNotWrapExceptions) == 0;
1748 if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0
1749 && (IsValueType))
1751 server = CreateInstanceDefaultCtor(publicOnly, false, true, wrapExceptions);
1753 else
1755 ConstructorInfo[] candidates = GetConstructors(bindingAttr);
1756 List<MethodBase> matches = new List<MethodBase>(candidates.Length);
1758 // We cannot use Type.GetTypeArray here because some of the args might be null
1759 Type[] argsType = new Type[argCnt];
1760 for (int i = 0; i < argCnt; i++)
1762 if (args[i] != null)
1764 argsType[i] = args[i].GetType();
1768 for(int i = 0; i < candidates.Length; i ++)
1770 if (FilterApplyConstructorInfo((RuntimeConstructorInfo)candidates[i], bindingAttr, CallingConventions.Any, argsType))
1771 matches.Add(candidates[i]);
1774 MethodBase[] cons = new MethodBase[matches.Count];
1775 matches.CopyTo(cons);
1776 if (cons != null && cons.Length == 0)
1777 cons = null;
1779 if (cons == null)
1781 throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName));
1784 MethodBase invokeMethod;
1785 Object state = null;
1789 invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state);
1791 catch (MissingMethodException) { invokeMethod = null; }
1793 if (invokeMethod == null)
1795 throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName));
1798 if (invokeMethod.GetParametersNoCopy().Length == 0)
1800 if (args.Length != 0)
1803 Contract.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) ==
1804 CallingConventions.VarArgs);
1805 throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
1806 Environment.GetResourceString("NotSupported_CallToVarArg")));
1809 // fast path??
1810 server = Activator.CreateInstance(this, nonPublic: true, wrapExceptions: wrapExceptions);
1812 else
1814 server = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture);
1815 if (state != null)
1816 binder.ReorderArgumentArray(ref args, state);
1820 finally
1824 catch (Exception)
1826 throw;
1829 //Console.WriteLine(server);
1830 return server;
1833 // Helper to invoke the default (parameterless) ctor.
1834 // fillCache is set in the SL2/3 compat mode or when called from Marshal.PtrToStructure.
1835 [DebuggerStepThroughAttribute]
1836 [Diagnostics.DebuggerHidden]
1837 internal Object CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, bool wrapExceptions)
1839 if (IsByRefLike)
1840 throw new NotSupportedException (SR.NotSupported_ByRefLike);
1842 return CreateInstanceSlow(publicOnly, wrapExceptions, skipCheckThis, fillCache);
1845 #endregion
1848 #region keep in sync with object-internals.h
1849 MonoTypeInfo type_info;
1850 #endregion
1852 TypeCache cache;
1854 internal TypeCache Cache {
1855 get {
1856 if (cache == null)
1857 LazyInitializer.EnsureInitialized (ref cache, () => new TypeCache ());
1859 return cache;
1863 internal sealed class TypeCache
1865 public Enum.EnumInfo EnumInfo;
1866 public TypeCode TypeCode;
1870 internal RuntimeType (Object obj)
1872 throw new NotImplementedException ();
1875 internal RuntimeConstructorInfo GetDefaultConstructor ()
1877 RuntimeConstructorInfo ctor = null;
1879 if (type_info == null)
1880 type_info = new MonoTypeInfo ();
1881 else
1882 ctor = type_info.default_ctor;
1884 if (ctor == null) {
1885 var ctors = GetConstructors (BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
1887 for (int i = 0; i < ctors.Length; ++i) {
1888 if (ctors [i].GetParametersCount () == 0) {
1889 type_info.default_ctor = ctor = (RuntimeConstructorInfo) ctors [i];
1890 break;
1895 return ctor;
1898 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1899 extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
1901 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1902 extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
1904 internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
1906 if (fromNoninstanciated == null)
1907 throw new ArgumentNullException ("fromNoninstanciated");
1908 return GetCorrespondingInflatedMethod (fromNoninstanciated);
1911 internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
1913 if (fromNoninstanciated == null)
1914 throw new ArgumentNullException ("fromNoninstanciated");
1915 return GetCorrespondingInflatedConstructor (fromNoninstanciated);
1918 internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
1920 /* create sensible flags from given FieldInfo */
1921 BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
1922 flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
1923 return GetField (fromNoninstanciated.Name, flags);
1926 string GetDefaultMemberName ()
1928 object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
1929 return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
1932 RuntimeConstructorInfo m_serializationCtor;
1933 internal RuntimeConstructorInfo GetSerializationCtor()
1935 if (m_serializationCtor == null) {
1936 var s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
1938 m_serializationCtor = GetConstructor(
1939 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
1940 null,
1941 CallingConventions.Any,
1942 s_SICtorParamTypes,
1943 null) as RuntimeConstructorInfo;
1946 return m_serializationCtor;
1949 internal Object CreateInstanceSlow(bool publicOnly, bool wrapExceptions, bool skipCheckThis, bool fillCache)
1951 //bool bNeedSecurityCheck = true;
1952 //bool bCanBeCached = false;
1953 //bool bSecurityCheckOff = false;
1955 if (!skipCheckThis)
1956 CreateInstanceCheckThis();
1958 //if (!fillCache)
1959 // bSecurityCheckOff = true;
1961 return CreateInstanceMono (!publicOnly, wrapExceptions);
1964 object CreateInstanceMono (bool nonPublic, bool wrapExceptions)
1966 var ctor = GetDefaultConstructor ();
1967 if (!nonPublic && ctor != null && !ctor.IsPublic) {
1968 throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, FullName));
1971 if (ctor == null) {
1972 Type elementType = this.GetRootElementType();
1973 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
1974 throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
1976 if (IsValueType)
1977 return CreateInstanceInternal (this);
1979 throw new MissingMethodException ("Default constructor not found for type " + FullName);
1982 // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
1983 if (IsAbstract) {
1984 throw new MissingMethodException ("Cannot create an abstract class '{0}'.", FullName);
1987 return ctor.InternalInvoke (null, null, wrapExceptions);
1990 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
1992 bool failed = false;
1993 var res = TryConvertToType (value, ref failed);
1994 if (!failed)
1995 return res;
1997 if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
1998 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
2000 if (binder != null && binder != Type.DefaultBinder)
2001 return binder.ChangeType (value, this, culture);
2003 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
2006 object TryConvertToType (object value, ref bool failed)
2008 if (IsInstanceOfType (value)) {
2009 return value;
2012 if (IsByRef) {
2013 var elementType = GetElementType ();
2014 if (value == null || elementType.IsInstanceOfType (value)) {
2015 return value;
2019 if (value == null)
2020 return value;
2022 if (IsEnum) {
2023 var type = Enum.GetUnderlyingType (this);
2024 if (type == value.GetType ())
2025 return value;
2026 var res = IsConvertibleToPrimitiveType (value, this);
2027 if (res != null)
2028 return res;
2029 } else if (IsPrimitive) {
2030 var res = IsConvertibleToPrimitiveType (value, this);
2031 if (res != null)
2032 return res;
2033 } else if (IsPointer) {
2034 var vtype = value.GetType ();
2035 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
2036 return value;
2037 if (value is Pointer pointer) {
2038 Type pointerType = pointer.GetPointerType ();
2039 if (pointerType == this)
2040 return pointer.GetPointerValue ();
2044 failed = true;
2045 return null;
2048 // Binder uses some incompatible conversion rules. For example
2049 // int value cannot be used with decimal parameter but in other
2050 // ways it's more flexible than normal convertor, for example
2051 // long value can be used with int based enum
2052 static object IsConvertibleToPrimitiveType (object value, Type targetType)
2054 var type = value.GetType ();
2055 if (type.IsEnum) {
2056 type = Enum.GetUnderlyingType (type);
2057 if (type == targetType)
2058 return value;
2061 var from = Type.GetTypeCode (type);
2062 var to = Type.GetTypeCode (targetType);
2064 switch (to) {
2065 case TypeCode.Char:
2066 switch (from) {
2067 case TypeCode.Byte:
2068 return (Char) (Byte) value;
2069 case TypeCode.UInt16:
2070 return value;
2072 break;
2073 case TypeCode.Int16:
2074 switch (from) {
2075 case TypeCode.Byte:
2076 return (Int16) (Byte) value;
2077 case TypeCode.SByte:
2078 return (Int16) (SByte) value;
2080 break;
2081 case TypeCode.UInt16:
2082 switch (from) {
2083 case TypeCode.Byte:
2084 return (UInt16) (Byte) value;
2085 case TypeCode.Char:
2086 return value;
2088 break;
2089 case TypeCode.Int32:
2090 switch (from) {
2091 case TypeCode.Byte:
2092 return (Int32) (Byte) value;
2093 case TypeCode.SByte:
2094 return (Int32) (SByte) value;
2095 case TypeCode.Char:
2096 return (Int32) (Char) value;
2097 case TypeCode.Int16:
2098 return (Int32) (Int16) value;
2099 case TypeCode.UInt16:
2100 return (Int32) (UInt16) value;
2102 break;
2103 case TypeCode.UInt32:
2104 switch (from) {
2105 case TypeCode.Byte:
2106 return (UInt32) (Byte) value;
2107 case TypeCode.Char:
2108 return (UInt32) (Char) value;
2109 case TypeCode.UInt16:
2110 return (UInt32) (UInt16) value;
2112 break;
2113 case TypeCode.Int64:
2114 switch (from) {
2115 case TypeCode.Byte:
2116 return (Int64) (Byte) value;
2117 case TypeCode.SByte:
2118 return (Int64) (SByte) value;
2119 case TypeCode.Int16:
2120 return (Int64) (Int16) value;
2121 case TypeCode.Char:
2122 return (Int64) (Char) value;
2123 case TypeCode.UInt16:
2124 return (Int64) (UInt16) value;
2125 case TypeCode.Int32:
2126 return (Int64) (Int32) value;
2127 case TypeCode.UInt32:
2128 return (Int64) (UInt32) value;
2130 break;
2131 case TypeCode.UInt64:
2132 switch (from) {
2133 case TypeCode.Byte:
2134 return (UInt64) (Byte) value;
2135 case TypeCode.Char:
2136 return (UInt64) (Char) value;
2137 case TypeCode.UInt16:
2138 return (UInt64) (UInt16) value;
2139 case TypeCode.UInt32:
2140 return (UInt64) (UInt32) value;
2142 break;
2143 case TypeCode.Single:
2144 switch (from) {
2145 case TypeCode.Byte:
2146 return (Single) (Byte) value;
2147 case TypeCode.SByte:
2148 return (Single) (SByte) value;
2149 case TypeCode.Int16:
2150 return (Single) (Int16) value;
2151 case TypeCode.Char:
2152 return (Single) (Char) value;
2153 case TypeCode.UInt16:
2154 return (Single) (UInt16) value;
2155 case TypeCode.Int32:
2156 return (Single) (Int32) value;
2157 case TypeCode.UInt32:
2158 return (Single) (UInt32) value;
2159 case TypeCode.Int64:
2160 return (Single) (Int64) value;
2161 case TypeCode.UInt64:
2162 return (Single) (UInt64) value;
2164 break;
2165 case TypeCode.Double:
2166 switch (from) {
2167 case TypeCode.Byte:
2168 return (Double) (Byte) value;
2169 case TypeCode.SByte:
2170 return (Double) (SByte) value;
2171 case TypeCode.Char:
2172 return (Double) (Char) value;
2173 case TypeCode.Int16:
2174 return (Double) (Int16) value;
2175 case TypeCode.UInt16:
2176 return (Double) (UInt16) value;
2177 case TypeCode.Int32:
2178 return (Double) (Int32) value;
2179 case TypeCode.UInt32:
2180 return (Double) (UInt32) value;
2181 case TypeCode.Int64:
2182 return (Double) (Int64) value;
2183 case TypeCode.UInt64:
2184 return (Double) (UInt64) value;
2185 case TypeCode.Single:
2186 return (Double) (Single) value;
2188 break;
2191 // Everything else is rejected
2192 return null;
2195 string GetCachedName (TypeNameKind kind)
2197 switch (kind) {
2198 case TypeNameKind.SerializationName:
2199 return ToString ();
2200 default:
2201 throw new NotImplementedException ();
2205 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2206 extern Type make_array_type (int rank);
2208 public override Type MakeArrayType ()
2210 return make_array_type (0);
2213 public override Type MakeArrayType (int rank)
2215 if (rank < 1 || rank > 255)
2216 throw new IndexOutOfRangeException ();
2217 return make_array_type (rank);
2220 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2221 extern Type make_byref_type ();
2223 public override Type MakeByRefType ()
2225 if (IsByRef)
2226 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
2227 return make_byref_type ();
2230 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2231 static extern Type MakePointerType (Type type);
2233 public override Type MakePointerType ()
2235 if (IsByRef)
2236 throw new TypeLoadException ($"Could not load type '{GetType()}' from assembly '{AssemblyQualifiedName}");
2237 return MakePointerType (this);
2240 public override StructLayoutAttribute? StructLayoutAttribute {
2241 get {
2242 return GetStructLayoutAttribute ();
2246 public override bool ContainsGenericParameters {
2247 get {
2248 if (IsGenericParameter)
2249 return true;
2251 if (IsGenericType) {
2252 foreach (Type arg in GetGenericArguments ())
2253 if (arg.ContainsGenericParameters)
2254 return true;
2257 if (HasElementType)
2258 return GetElementType ().ContainsGenericParameters;
2260 return false;
2264 public override Type[] GetGenericParameterConstraints ()
2266 if (!IsGenericParameter)
2267 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
2269 var paramInfo = new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this));
2270 Type[] constraints = paramInfo.Constraints;
2272 return constraints ?? Array.Empty<Type> ();
2275 internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
2277 var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
2278 var ctor = gt.GetDefaultConstructor ();
2279 return ctor.InternalInvoke (null, null, wrapExceptions: true);
2282 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2283 static extern Type MakeGenericType (Type gt, Type [] types);
2285 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2286 internal extern IntPtr GetMethodsByName_native (IntPtr namePtr, BindingFlags bindingAttr, MemberListType listType);
2288 internal RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, MemberListType listType, RuntimeType reflectedType)
2290 var refh = new RuntimeTypeHandle (reflectedType);
2291 using (var namePtr = new Mono.SafeStringMarshal (name))
2292 using (var h = new Mono.SafeGPtrArrayHandle (GetMethodsByName_native (namePtr.Value, bindingAttr, listType))) {
2293 var n = h.Length;
2294 var a = new RuntimeMethodInfo [n];
2295 for (int i = 0; i < n; i++) {
2296 var mh = new RuntimeMethodHandle (h[i]);
2297 a[i] = (RuntimeMethodInfo) RuntimeMethodInfo.GetMethodFromHandleNoGenericCheck (mh, refh);
2299 return a;
2303 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2304 extern IntPtr GetPropertiesByName_native (IntPtr name, BindingFlags bindingAttr, MemberListType listType);
2306 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2307 extern IntPtr GetConstructors_native (BindingFlags bindingAttr);
2309 RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, RuntimeType reflectedType)
2311 var refh = new RuntimeTypeHandle (reflectedType);
2312 using (var h = new Mono.SafeGPtrArrayHandle (GetConstructors_native (bindingAttr))) {
2313 var n = h.Length;
2314 var a = new RuntimeConstructorInfo [n];
2315 for (int i = 0; i < n; i++) {
2316 var mh = new RuntimeMethodHandle (h[i]);
2317 a[i] = (RuntimeConstructorInfo) RuntimeMethodInfo.GetMethodFromHandleNoGenericCheck (mh, refh);
2319 return a;
2323 RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, MemberListType listType, RuntimeType reflectedType)
2325 var refh = new RuntimeTypeHandle (reflectedType);
2326 using (var namePtr = new Mono.SafeStringMarshal (name))
2327 using (var h = new Mono.SafeGPtrArrayHandle (GetPropertiesByName_native (namePtr.Value, bindingAttr, listType))) {
2328 var n = h.Length;
2329 var a = new RuntimePropertyInfo [n];
2330 for (int i = 0; i < n; i++) {
2331 var ph = new Mono.RuntimePropertyHandle (h[i]);
2332 a[i] = (RuntimePropertyInfo) RuntimePropertyInfo.GetPropertyFromHandle (ph, refh);
2334 return a;
2338 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
2340 if (IsGenericParameter)
2341 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
2343 if ((object)ifaceType == null)
2344 throw new ArgumentNullException("ifaceType");
2346 RuntimeType ifaceRtType = ifaceType as RuntimeType;
2348 if (ifaceRtType == null)
2349 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
2351 InterfaceMapping res;
2352 if (!ifaceType.IsInterface)
2353 throw new ArgumentException ("Argument must be an interface.", "ifaceType");
2354 if (IsInterface)
2355 throw new ArgumentException ("'this' type cannot be an interface itself");
2356 res.TargetType = this;
2357 res.InterfaceType = ifaceType;
2358 GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
2359 if (res.TargetMethods == null)
2360 throw new ArgumentException ("Interface not found", "ifaceType");
2362 return res;
2365 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2366 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
2368 public override Guid GUID {
2369 get {
2370 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
2371 if (att.Length == 0)
2372 return Guid.Empty;
2373 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
2377 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2378 internal extern void GetPacking (out int packing, out int size);
2380 public override string ToString()
2382 return getFullName (false, false);
2385 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2386 static extern object CreateInstanceInternal (Type type);
2388 public extern override MethodBase? DeclaringMethod {
2389 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2390 get;
2393 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2394 internal extern string getFullName(bool full_name, bool assembly_qualified);
2396 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2397 extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
2399 GenericParameterAttributes GetGenericParameterAttributes () {
2400 return (new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this))).Attributes;
2403 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2404 extern int GetGenericParameterPosition ();
2406 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2407 extern IntPtr GetEvents_native (IntPtr name, MemberListType listType);
2409 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2410 extern IntPtr GetFields_native (IntPtr name, BindingFlags bindingAttr, MemberListType listType);
2412 RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, MemberListType listType, RuntimeType reflectedType)
2414 var refh = new RuntimeTypeHandle (reflectedType);
2415 using (var namePtr = new Mono.SafeStringMarshal (name))
2416 using (var h = new Mono.SafeGPtrArrayHandle (GetFields_native (namePtr.Value, bindingAttr, listType))) {
2417 int n = h.Length;
2418 var a = new RuntimeFieldInfo[n];
2419 for (int i = 0; i < n; i++) {
2420 var fh = new RuntimeFieldHandle (h[i]);
2421 a[i] = (RuntimeFieldInfo) FieldInfo.GetFieldFromHandle (fh, refh);
2423 return a;
2427 RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, MemberListType listType, RuntimeType reflectedType)
2429 var refh = new RuntimeTypeHandle (reflectedType);
2430 using (var namePtr = new Mono.SafeStringMarshal (name))
2431 using (var h = new Mono.SafeGPtrArrayHandle (GetEvents_native (namePtr.Value, listType))) {
2432 int n = h.Length;
2433 var a = new RuntimeEventInfo[n];
2434 for (int i = 0; i < n; i++) {
2435 var eh = new Mono.RuntimeEventHandle (h[i]);
2436 a[i] = (RuntimeEventInfo) RuntimeEventInfo.GetEventFromHandle (eh, refh);
2438 return a;
2442 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2443 public extern override Type[] GetInterfaces();
2445 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2446 extern IntPtr GetNestedTypes_native (IntPtr name, BindingFlags bindingAttr, MemberListType listType);
2448 RuntimeType[] GetNestedTypes_internal (string displayName, BindingFlags bindingAttr, MemberListType listType)
2450 string internalName = null;
2451 if (displayName != null)
2452 internalName = displayName;
2453 using (var namePtr = new Mono.SafeStringMarshal (internalName))
2454 using (var h = new Mono.SafeGPtrArrayHandle (GetNestedTypes_native (namePtr.Value, bindingAttr, listType))) {
2455 int n = h.Length;
2456 var a = new RuntimeType [n];
2457 for (int i = 0; i < n; i++) {
2458 var th = new RuntimeTypeHandle (h[i]);
2459 a[i] = (RuntimeType) Type.GetTypeFromHandle (th);
2461 return a;
2465 public override string? AssemblyQualifiedName {
2466 get {
2467 return getFullName (true, true);
2471 public extern override Type? DeclaringType {
2472 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2473 get;
2476 public extern override string Name {
2477 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2478 get;
2481 public extern override string? Namespace {
2482 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2483 get;
2486 public override string? FullName {
2487 get {
2488 // https://bugzilla.xamarin.com/show_bug.cgi?id=57938
2489 if (IsGenericType && ContainsGenericParameters && !IsGenericTypeDefinition)
2490 return null;
2492 string fullName;
2493 // This doesn't need locking
2494 if (type_info == null)
2495 type_info = new MonoTypeInfo ();
2496 if ((fullName = type_info.full_name) == null)
2497 fullName = type_info.full_name = getFullName (true, false);
2499 return fullName;
2503 public sealed override bool HasSameMetadataDefinitionAs (MemberInfo other) => HasSameMetadataDefinitionAsCore<RuntimeType> (other);
2505 public override bool IsSZArray {
2506 get {
2507 // TODO: intrinsic
2508 return IsArray && ReferenceEquals (this, GetElementType ().MakeArrayType ());
2512 internal override bool IsUserType {
2513 get {
2514 return false;
2518 public override bool IsSubclassOf(Type type)
2520 if ((object)type == null)
2521 throw new ArgumentNullException("type");
2523 RuntimeType rtType = type as RuntimeType;
2524 if (rtType == null)
2525 return false;
2527 return RuntimeTypeHandle.IsSubclassOf (this, rtType);
2530 private const int DEFAULT_PACKING_SIZE = 8;
2532 internal StructLayoutAttribute GetStructLayoutAttribute ()
2534 if (IsInterface || HasElementType || IsGenericParameter)
2535 return null;
2537 int pack = 0, size = 0;
2538 LayoutKind layoutKind = LayoutKind.Auto;
2539 switch (Attributes & TypeAttributes.LayoutMask)
2541 case TypeAttributes.ExplicitLayout: layoutKind = LayoutKind.Explicit; break;
2542 case TypeAttributes.AutoLayout: layoutKind = LayoutKind.Auto; break;
2543 case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break;
2544 default: break;
2547 CharSet charSet = CharSet.None;
2548 switch (Attributes & TypeAttributes.StringFormatMask)
2550 case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break;
2551 case TypeAttributes.AutoClass: charSet = CharSet.Auto; break;
2552 case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break;
2553 default: break;
2556 GetPacking (out pack, out size);
2558 // Metadata parameter checking should not have allowed 0 for packing size.
2559 // The runtime later converts a packing size of 0 to 8 so do the same here
2560 // because it's more useful from a user perspective.
2561 if (pack == 0)
2562 pack = DEFAULT_PACKING_SIZE;
2564 return new StructLayoutAttribute (layoutKind) { Pack = pack, Size = size, CharSet = charSet };
2568 // Contains information about the type which is expensive to compute
2569 [StructLayout (LayoutKind.Sequential)]
2570 internal class MonoTypeInfo {
2571 // this is the displayed form: special characters
2572 // ,+*&*[]\ in the identifier portions of the names
2573 // have been escaped with a leading backslash (\)
2574 public string full_name;
2575 public RuntimeConstructorInfo default_ctor;