Merge pull request #19125 from mikedn/cse-extract
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / shared / System / Type.cs
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.
4
5 using System.Threading;
6 using System.Reflection;
7 using System.Diagnostics;
8 using System.Globalization;
9 using System.Runtime.InteropServices;
10
11 namespace System
12 {
13     public abstract partial class Type : MemberInfo, IReflect
14     {
15         protected Type() { }
16
17         public override MemberTypes MemberType => MemberTypes.TypeInfo;
18
19         public new Type GetType() => base.GetType();
20
21         public abstract string Namespace { get; }
22         public abstract string AssemblyQualifiedName { get; }
23         public abstract string FullName { get; }
24
25         public abstract Assembly Assembly { get; }
26         public abstract new Module Module { get; }
27
28         public bool IsNested => DeclaringType != null;
29         public override Type DeclaringType => null;
30         public virtual MethodBase DeclaringMethod => null;
31
32         public override Type ReflectedType => null;
33         public abstract Type UnderlyingSystemType { get; }
34
35         public virtual bool IsTypeDefinition { get { throw NotImplemented.ByDesign; } }
36         public bool IsArray => IsArrayImpl();
37         protected abstract bool IsArrayImpl();
38         public bool IsByRef => IsByRefImpl();
39         protected abstract bool IsByRefImpl();
40         public bool IsPointer => IsPointerImpl();
41         protected abstract bool IsPointerImpl();
42         public virtual bool IsConstructedGenericType { get { throw NotImplemented.ByDesign; } }
43         public virtual bool IsGenericParameter => false;
44         public virtual bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null;
45         public virtual bool IsGenericMethodParameter => IsGenericParameter && DeclaringMethod != null;
46         public virtual bool IsGenericType => false;
47         public virtual bool IsGenericTypeDefinition => false;
48
49         public virtual bool IsSZArray { get { throw NotImplemented.ByDesign; } }
50         public virtual bool IsVariableBoundArray => IsArray && !IsSZArray;
51
52         public virtual bool IsByRefLike => throw new NotSupportedException(SR.NotSupported_SubclassOverride);
53
54         public bool HasElementType => HasElementTypeImpl();
55         protected abstract bool HasElementTypeImpl();
56         public abstract Type GetElementType();
57
58         public virtual int GetArrayRank() { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
59
60         public virtual Type GetGenericTypeDefinition() { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
61         public virtual Type[] GenericTypeArguments => (IsGenericType && !IsGenericTypeDefinition) ? GetGenericArguments() : Array.Empty<Type>();
62         public virtual Type[] GetGenericArguments() { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
63
64         public virtual int GenericParameterPosition { get { throw new InvalidOperationException(SR.Arg_NotGenericParameter); } }
65         public virtual GenericParameterAttributes GenericParameterAttributes { get { throw new NotSupportedException(); } }
66         public virtual Type[] GetGenericParameterConstraints()
67         {
68             if (!IsGenericParameter)
69                 throw new InvalidOperationException(SR.Arg_NotGenericParameter);
70             throw new InvalidOperationException();
71         }
72
73         public TypeAttributes Attributes => GetAttributeFlagsImpl();
74         protected abstract TypeAttributes GetAttributeFlagsImpl();
75
76         public bool IsAbstract => (GetAttributeFlagsImpl() & TypeAttributes.Abstract) != 0;
77         public bool IsImport => (GetAttributeFlagsImpl() & TypeAttributes.Import) != 0;
78         public bool IsSealed => (GetAttributeFlagsImpl() & TypeAttributes.Sealed) != 0;
79         public bool IsSpecialName => (GetAttributeFlagsImpl() & TypeAttributes.SpecialName) != 0;
80
81         public bool IsClass => (GetAttributeFlagsImpl() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class && !IsValueType;
82
83         public bool IsNestedAssembly => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly;
84         public bool IsNestedFamANDAssem => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem;
85         public bool IsNestedFamily => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily;
86         public bool IsNestedFamORAssem => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem;
87         public bool IsNestedPrivate => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate;
88         public bool IsNestedPublic => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic;
89         public bool IsNotPublic => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic;
90         public bool IsPublic => (GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.Public;
91
92         public bool IsAutoLayout => (GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout;
93         public bool IsExplicitLayout => (GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout;
94         public bool IsLayoutSequential => (GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout;
95
96         public bool IsAnsiClass => (GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass;
97         public bool IsAutoClass => (GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass;
98         public bool IsUnicodeClass => (GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass;
99
100         public bool IsCOMObject => IsCOMObjectImpl();
101         protected abstract bool IsCOMObjectImpl();
102         public bool IsContextful => IsContextfulImpl();
103         protected virtual bool IsContextfulImpl() => false;
104
105         public virtual bool IsCollectible => true;
106
107         public virtual bool IsEnum => IsSubclassOf(typeof(Enum));
108         public bool IsMarshalByRef => IsMarshalByRefImpl();
109         protected virtual bool IsMarshalByRefImpl() => false;
110         public bool IsPrimitive => IsPrimitiveImpl();
111         protected abstract bool IsPrimitiveImpl();
112         public bool IsValueType => IsValueTypeImpl();
113         protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType));
114
115         public virtual bool IsSignatureType => false;
116
117         public virtual bool IsSecurityCritical { get { throw NotImplemented.ByDesign; } }
118         public virtual bool IsSecuritySafeCritical { get { throw NotImplemented.ByDesign; } }
119         public virtual bool IsSecurityTransparent { get { throw NotImplemented.ByDesign; } }
120
121         public virtual StructLayoutAttribute StructLayoutAttribute { get { throw new NotSupportedException(); } }
122         public ConstructorInfo TypeInitializer => GetConstructorImpl(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, Type.EmptyTypes, null);
123
124         public ConstructorInfo GetConstructor(Type[] types) => GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null);
125         public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => GetConstructor(bindingAttr, binder, CallingConventions.Any, types, modifiers);
126         public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
127         {
128             if (types == null)
129                 throw new ArgumentNullException(nameof(types));
130             for (int i = 0; i < types.Length; i++)
131             {
132                 if (types[i] == null)
133                     throw new ArgumentNullException(nameof(types));
134             }
135             return GetConstructorImpl(bindingAttr, binder, callConvention, types, modifiers);
136         }
137         protected abstract ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers);
138
139         public ConstructorInfo[] GetConstructors() => GetConstructors(BindingFlags.Public | BindingFlags.Instance);
140         public abstract ConstructorInfo[] GetConstructors(BindingFlags bindingAttr);
141
142         public EventInfo GetEvent(string name) => GetEvent(name, Type.DefaultLookup);
143         public abstract EventInfo GetEvent(string name, BindingFlags bindingAttr);
144
145         public virtual EventInfo[] GetEvents() => GetEvents(Type.DefaultLookup);
146         public abstract EventInfo[] GetEvents(BindingFlags bindingAttr);
147
148         public FieldInfo GetField(string name) => GetField(name, Type.DefaultLookup);
149         public abstract FieldInfo GetField(string name, BindingFlags bindingAttr);
150
151         public FieldInfo[] GetFields() => GetFields(Type.DefaultLookup);
152         public abstract FieldInfo[] GetFields(BindingFlags bindingAttr);
153
154         public MemberInfo[] GetMember(string name) => GetMember(name, Type.DefaultLookup);
155         public virtual MemberInfo[] GetMember(string name, BindingFlags bindingAttr) => GetMember(name, MemberTypes.All, bindingAttr);
156         public virtual MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
157
158         public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup);
159         public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr);
160
161         public MethodInfo GetMethod(string name) => GetMethod(name, Type.DefaultLookup);
162         public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
163         {
164             if (name == null)
165                 throw new ArgumentNullException(nameof(name));
166             return GetMethodImpl(name, bindingAttr, null, CallingConventions.Any, null, null);
167         }
168
169         public MethodInfo GetMethod(string name, Type[] types) => GetMethod(name, types, null);
170         public MethodInfo GetMethod(string name, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, Type.DefaultLookup, null, types, modifiers);
171         public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, bindingAttr, binder, CallingConventions.Any, types, modifiers);
172         public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
173         {
174             if (name == null)
175                 throw new ArgumentNullException(nameof(name));
176             if (types == null)
177                 throw new ArgumentNullException(nameof(types));
178             for (int i = 0; i < types.Length; i++)
179             {
180                 if (types[i] == null)
181                     throw new ArgumentNullException(nameof(types));
182             }
183             return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);
184         }
185
186         protected abstract MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers);
187
188         public MethodInfo GetMethod(string name, int genericParameterCount, Type[] types) => GetMethod(name, genericParameterCount, types, null);
189         public MethodInfo GetMethod(string name, int genericParameterCount, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, genericParameterCount, Type.DefaultLookup, null, types, modifiers);
190         public MethodInfo GetMethod(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, genericParameterCount, bindingAttr, binder, CallingConventions.Any, types, modifiers);
191         public MethodInfo GetMethod(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
192         {
193             if (name == null)
194                 throw new ArgumentNullException(nameof(name));
195             if (genericParameterCount < 0)
196                 throw new ArgumentException(SR.ArgumentOutOfRange_NeedNonNegNum, nameof(genericParameterCount));
197             if (types == null)
198                 throw new ArgumentNullException(nameof(types));
199             for (int i = 0; i < types.Length; i++)
200             {
201                 if (types[i] == null)
202                     throw new ArgumentNullException(nameof(types));
203             }
204             return GetMethodImpl(name, genericParameterCount, bindingAttr, binder, callConvention, types, modifiers);
205         }
206
207         protected virtual MethodInfo GetMethodImpl(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotSupportedException();
208
209         public MethodInfo[] GetMethods() => GetMethods(Type.DefaultLookup);
210         public abstract MethodInfo[] GetMethods(BindingFlags bindingAttr);
211
212         public Type GetNestedType(string name) => GetNestedType(name, Type.DefaultLookup);
213         public abstract Type GetNestedType(string name, BindingFlags bindingAttr);
214
215         public Type[] GetNestedTypes() => GetNestedTypes(Type.DefaultLookup);
216         public abstract Type[] GetNestedTypes(BindingFlags bindingAttr);
217
218         public PropertyInfo GetProperty(string name) => GetProperty(name, Type.DefaultLookup);
219         public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
220         {
221             if (name == null)
222                 throw new ArgumentNullException(nameof(name));
223             return GetPropertyImpl(name, bindingAttr, null, null, null, null);
224         }
225
226         public PropertyInfo GetProperty(string name, Type returnType)
227         {
228             if (name == null)
229                 throw new ArgumentNullException(nameof(name));
230             if (returnType == null)
231                 throw new ArgumentNullException(nameof(returnType));
232             return GetPropertyImpl(name, Type.DefaultLookup, null, returnType, null, null);
233         }
234
235         public PropertyInfo GetProperty(string name, Type[] types) => GetProperty(name, null, types);
236         public PropertyInfo GetProperty(string name, Type returnType, Type[] types) => GetProperty(name, returnType, types, null);
237         public PropertyInfo GetProperty(string name, Type returnType, Type[] types, ParameterModifier[] modifiers) => GetProperty(name, Type.DefaultLookup, null, returnType, types, modifiers);
238         public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
239         {
240             if (name == null)
241                 throw new ArgumentNullException(nameof(name));
242             if (types == null)
243                 throw new ArgumentNullException(nameof(types));
244             return GetPropertyImpl(name, bindingAttr, binder, returnType, types, modifiers);
245         }
246
247         protected abstract PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers);
248
249         public PropertyInfo[] GetProperties() => GetProperties(Type.DefaultLookup);
250         public abstract PropertyInfo[] GetProperties(BindingFlags bindingAttr);
251
252         public virtual MemberInfo[] GetDefaultMembers() { throw NotImplemented.ByDesign; }
253
254         public virtual RuntimeTypeHandle TypeHandle { get { throw new NotSupportedException(); } }
255         public static RuntimeTypeHandle GetTypeHandle(object o)
256         {
257             if (o == null)
258                 throw new ArgumentNullException(null, SR.Arg_InvalidHandle);
259             Type type = o.GetType();
260             return type.TypeHandle;
261         }
262
263         public static Type[] GetTypeArray(object[] args)
264         {
265             if (args == null)
266                 throw new ArgumentNullException(nameof(args));
267
268             Type[] cls = new Type[args.Length];
269             for (int i = 0; i < cls.Length; i++)
270             {
271                 if (args[i] == null)
272                     throw new ArgumentNullException();
273                 cls[i] = args[i].GetType();
274             }
275             return cls;
276         }
277
278         public static TypeCode GetTypeCode(Type type)
279         {
280             if (type == null)
281                 return TypeCode.Empty;
282             return type.GetTypeCodeImpl();
283         }
284         protected virtual TypeCode GetTypeCodeImpl()
285         {
286             if (this != UnderlyingSystemType && UnderlyingSystemType != null)
287                 return Type.GetTypeCode(UnderlyingSystemType);
288
289             return TypeCode.Object;
290         }
291
292         public abstract Guid GUID { get; }
293
294         public static Type GetTypeFromCLSID(Guid clsid) => GetTypeFromCLSID(clsid, null, throwOnError: false);
295         public static Type GetTypeFromCLSID(Guid clsid, bool throwOnError) => GetTypeFromCLSID(clsid, null, throwOnError: throwOnError);
296         public static Type GetTypeFromCLSID(Guid clsid, string server) => GetTypeFromCLSID(clsid, server, throwOnError: false);
297
298         public static Type GetTypeFromProgID(string progID) => GetTypeFromProgID(progID, null, throwOnError: false);
299         public static Type GetTypeFromProgID(string progID, bool throwOnError) => GetTypeFromProgID(progID, null, throwOnError: throwOnError);
300         public static Type GetTypeFromProgID(string progID, string server) => GetTypeFromProgID(progID, server, throwOnError: false);
301
302         public abstract Type BaseType { get; }
303
304         [DebuggerHidden]
305         [DebuggerStepThrough]
306         public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args) => InvokeMember(name, invokeAttr, binder, target, args, null, null, null);
307
308         [DebuggerHidden]
309         [DebuggerStepThrough]
310         public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, CultureInfo culture) => InvokeMember(name, invokeAttr, binder, target, args, null, culture, null);
311         public abstract object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters);
312
313         public Type GetInterface(string name) => GetInterface(name, ignoreCase: false);
314         public abstract Type GetInterface(string name, bool ignoreCase);
315         public abstract Type[] GetInterfaces();
316
317         public virtual InterfaceMapping GetInterfaceMap(Type interfaceType) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
318
319         public virtual bool IsInstanceOfType(object o) => o == null ? false : IsAssignableFrom(o.GetType());
320         public virtual bool IsEquivalentTo(Type other) => this == other;
321
322         public virtual Type GetEnumUnderlyingType()
323         {
324             if (!IsEnum)
325                 throw new ArgumentException(SR.Arg_MustBeEnum, "enumType");
326
327             FieldInfo[] fields = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
328             if (fields == null || fields.Length != 1)
329                 throw new ArgumentException(SR.Argument_InvalidEnum, "enumType");
330
331             return fields[0].FieldType;
332         }
333         public virtual Array GetEnumValues()
334         {
335             if (!IsEnum)
336                 throw new ArgumentException(SR.Arg_MustBeEnum, "enumType");
337
338             // We don't support GetEnumValues in the default implementation because we cannot create an array of
339             // a non-runtime type. If there is strong need we can consider returning an object or int64 array.
340             throw NotImplemented.ByDesign;
341         }
342
343         public virtual Type MakeArrayType() { throw new NotSupportedException(); }
344         public virtual Type MakeArrayType(int rank) { throw new NotSupportedException(); }
345         public virtual Type MakeByRefType() { throw new NotSupportedException(); }
346         public virtual Type MakeGenericType(params Type[] typeArguments) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
347         public virtual Type MakePointerType() { throw new NotSupportedException(); }
348
349         public static Type MakeGenericSignatureType(Type genericTypeDefinition, params Type[] typeArguments) => new SignatureConstructedGenericType(genericTypeDefinition, typeArguments);
350
351         public static Type MakeGenericMethodParameter(int position)
352         {
353             if (position < 0)
354                 throw new ArgumentException(SR.ArgumentOutOfRange_NeedNonNegNum, nameof(position));
355             return new SignatureGenericMethodParameterType(position);
356         }
357
358         public override string ToString() => "Type: " + Name;  // Why do we add the "Type: " prefix?
359
360         public override bool Equals(object o) => o == null ? false : Equals(o as Type);
361         public override int GetHashCode()
362         {
363             Type systemType = UnderlyingSystemType;
364             if (!object.ReferenceEquals(systemType, this))
365                 return systemType.GetHashCode();
366             return base.GetHashCode();
367         }
368         public virtual bool Equals(Type o) => o == null ? false : object.ReferenceEquals(this.UnderlyingSystemType, o.UnderlyingSystemType);
369
370         public static Type ReflectionOnlyGetType(string typeName, bool throwIfNotFound, bool ignoreCase) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); }
371
372         public static Binder DefaultBinder
373         {
374             get
375             {
376                 if (s_defaultBinder == null)
377                 {
378                     DefaultBinder binder = new DefaultBinder();
379                     Interlocked.CompareExchange<Binder>(ref s_defaultBinder, binder, null);
380                 }
381                 return s_defaultBinder;
382             }
383         }
384
385         private static volatile Binder s_defaultBinder;
386
387         public static readonly char Delimiter = '.';
388         public static readonly Type[] EmptyTypes = Array.Empty<Type>();
389         public static readonly object Missing = System.Reflection.Missing.Value;
390
391         public static readonly MemberFilter FilterAttribute = FilterAttributeImpl;
392         public static readonly MemberFilter FilterName = (m, c) => FilterNameImpl(m, c, StringComparison.Ordinal);
393         public static readonly MemberFilter FilterNameIgnoreCase = (m, c) => FilterNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
394
395         private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
396     }
397 }