// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using CultureInfo = System.Globalization.CultureInfo; namespace System.Reflection { /// <summary> /// Base class for modified types and standalone modified type. /// Design supports code sharing between different runtimes and lazy loading of custom modifiers. /// </summary> internal partial class ModifiedType : Type { private readonly TypeSignature _typeSignature; private readonly Type _unmodifiedType; internal ModifiedType(Type unmodifiedType, TypeSignature typeSignature) { _unmodifiedType = unmodifiedType; _typeSignature = typeSignature; } /// <summary> /// Factory to create a node recursively based on the underlying, unmodified type. /// A type tree is formed due to arrays and pointers having an element type, function pointers /// having a return type and parameter types, and generic types having argument types. /// </summary> protected static Type Create(Type unmodifiedType, TypeSignature typeSignature) { Type modifiedType; if (unmodifiedType.IsFunctionPointer) { modifiedType = new ModifiedFunctionPointerType(unmodifiedType, typeSignature); } else if (unmodifiedType.HasElementType) { modifiedType = new ModifiedHasElementType(unmodifiedType, typeSignature); } else if (unmodifiedType.IsGenericType) { modifiedType = new ModifiedGenericType(unmodifiedType, typeSignature); } else { modifiedType = new ModifiedType(unmodifiedType, typeSignature); } return modifiedType; } protected Type UnmodifiedType => _unmodifiedType; // Below are the multitude of Type overloads. We throw NSE for members that would return an unmodified Type // directly or indirectly. We do this in case we want to support returning modified types instead. public override Type[] GetRequiredCustomModifiers() { // No caching is performed; as is the case with FieldInfo.GetCustomModifiers and friends. return GetCustomModifiers(required: true); } public override Type[] GetOptionalCustomModifiers() { // No caching is performed; as is the case with FieldInfo.GetCustomModifiers and friends. return GetCustomModifiers(required: false); } // Modified types do not support Equals. That would need to include custom modifiers and any parameterized types recursively. // UnderlyingSystemType.Equals() should should be used if basic equality is necessary. public override bool Equals([NotNullWhen(true)] object? obj) => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override bool Equals(Type? other) => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override int GetHashCode() => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override string ToString() => _unmodifiedType.ToString(); public override Type UnderlyingSystemType => _unmodifiedType; public override GenericParameterAttributes GenericParameterAttributes => _unmodifiedType.GenericParameterAttributes; public override bool ContainsGenericParameters => _unmodifiedType.ContainsGenericParameters; public override Type GetGenericTypeDefinition() => _unmodifiedType.GetGenericTypeDefinition(); public override bool IsGenericType => _unmodifiedType.IsGenericType; public override Type? GetNullableUnderlyingType() => _unmodifiedType.GetNullableUnderlyingType() is not null ? GetGenericArguments()[0] : null; [DynamicallyAccessedMembers(InvokeMemberMembers)] public override object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override Guid GUID => _unmodifiedType.GUID; public override int MetadataToken => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override Module Module => _unmodifiedType.Module; public override Assembly Assembly => _unmodifiedType.Assembly; public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override string Name => _unmodifiedType.Name; public override string? FullName => _unmodifiedType.FullName; public override string? Namespace => _unmodifiedType.Namespace; public override string? AssemblyQualifiedName => _unmodifiedType.AssemblyQualifiedName; public override Type? BaseType => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override Type? DeclaringType => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override Type? ReflectedType => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public override FieldInfo? GetField(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override Type[] GetFunctionPointerCallingConventions() => _unmodifiedType.GetFunctionPointerCallingConventions(); public override Type[] GetFunctionPointerParameterTypes() => _unmodifiedType.GetFunctionPointerParameterTypes(); public override Type GetFunctionPointerReturnType() => _unmodifiedType.GetFunctionPointerReturnType(); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] public override Type? GetInterface(string name, bool ignoreCase) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] public override Type[] GetInterfaces() => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType) => _unmodifiedType.GetInterfaceMap(interfaceType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] public override EventInfo[] GetEvents() => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] protected override PropertyInfo? GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] public override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] public override Type[] GetNestedTypes(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] public override Type? GetNestedType(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(GetAllMembers)] public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); [DynamicallyAccessedMembers(GetAllMembers)] public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_ModifiedType); public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member) => throw new NotSupportedException(SR.NotSupported_ModifiedType); protected override TypeAttributes GetAttributeFlagsImpl() => _unmodifiedType.Attributes; public override int GetArrayRank() => _unmodifiedType.GetArrayRank(); public override bool IsTypeDefinition => _unmodifiedType.IsTypeDefinition; public override bool IsSZArray => _unmodifiedType.IsSZArray; public override bool IsVariableBoundArray => _unmodifiedType.IsVariableBoundArray; protected override bool IsArrayImpl() => _unmodifiedType.IsArray; public override bool IsEnum => _unmodifiedType.IsEnum; protected override bool IsPrimitiveImpl() => _unmodifiedType.IsPrimitive; protected override bool IsByRefImpl() => _unmodifiedType.IsByRef; public override bool IsGenericParameter => _unmodifiedType.IsGenericParameter; public override bool IsGenericTypeParameter => _unmodifiedType.IsGenericTypeParameter; public override bool IsGenericMethodParameter => _unmodifiedType.IsGenericMethodParameter; public override int GenericParameterPosition => _unmodifiedType.GenericParameterPosition; protected override bool IsPointerImpl() => _unmodifiedType.IsPointer; protected override bool IsValueTypeImpl() => _unmodifiedType.IsValueType; protected override bool IsCOMObjectImpl() => _unmodifiedType.IsCOMObject; public override bool IsByRefLike => _unmodifiedType.IsByRefLike; public override bool IsConstructedGenericType => _unmodifiedType.IsConstructedGenericType; public override bool IsCollectible => _unmodifiedType.IsCollectible; public override bool IsFunctionPointer => _unmodifiedType.IsFunctionPointer; public override bool IsUnmanagedFunctionPointer => _unmodifiedType.IsUnmanagedFunctionPointer; public override bool IsSecurityCritical => _unmodifiedType.IsSecurityCritical; public override bool IsSecuritySafeCritical => _unmodifiedType.IsSecuritySafeCritical; public override bool IsSecurityTransparent => _unmodifiedType.IsSecurityTransparent; public override Type? GetElementType() => _unmodifiedType.GetElementType(); // Supported protected override bool HasElementTypeImpl() => _unmodifiedType.HasElementType; // ICustomAttributeProvider public override object[] GetCustomAttributes(bool inherit) => _unmodifiedType.GetCustomAttributes(inherit); public override object[] GetCustomAttributes(Type attributeType, bool inherit) => _unmodifiedType.GetCustomAttributes(attributeType, inherit); public override bool IsDefined(Type attributeType, bool inherit) => _unmodifiedType.IsDefined(attributeType, inherit); } }