File: System\Reflection\Emit\TypeBuilderImpl.cs
Web Access
Project: src\src\libraries\System.Reflection.Emit\src\System.Reflection.Emit.csproj (System.Reflection.Emit)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
 
namespace System.Reflection.Emit
{
    internal sealed class TypeBuilderImpl : TypeBuilder
    {
        private readonly ModuleBuilderImpl _module;
        private readonly string _name;
        private readonly string? _namespace;
        private string? _strFullName;
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        private Type? _typeParent;
        private readonly TypeBuilderImpl? _declaringType;
        private GenericTypeParameterBuilderImpl[]? _typeParameters;
        private TypeAttributes _attributes;
        private PackingSize _packingSize;
        private int _typeSize;
        private Type? _enumUnderlyingType;
        private bool _isCreated;
 
        internal bool _isHiddenGlobalType;
        internal TypeDefinitionHandle _handle;
        internal int _firstFieldToken;
        internal int _firstMethodToken;
        internal int _firstPropertyToken;
        internal int _firstEventToken;
        internal readonly List<MethodBuilderImpl> _methodDefinitions = new();
        internal readonly List<FieldBuilderImpl> _fieldDefinitions = new();
        internal readonly List<ConstructorBuilderImpl> _constructorDefinitions = new();
        internal List<Type>? _interfaces;
        internal readonly List<PropertyBuilderImpl> _propertyDefinitions = new();
        internal readonly List<EventBuilderImpl> _eventDefinitions = new();
        internal List<CustomAttributeWrapper>? _customAttributes;
        internal Dictionary<Type, List<(MethodInfo ifaceMethod, MethodInfo targetMethod)>>? _methodOverrides;
 
        // Only for creating the global type
        internal TypeBuilderImpl(ModuleBuilderImpl module)
        {
            _name = "<Module>"; // Defined in ECMA-335 II.10.8
            _module = module;
            _isHiddenGlobalType = true;
            _handle = MetadataTokens.TypeDefinitionHandle(1);
        }
 
        internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes,
            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module,
            Type[]? interfaces, PackingSize packingSize, int typeSize, TypeBuilderImpl? enclosingType)
        {
            _name = fullName;
            _module = module;
            _attributes = typeAttributes;
            _packingSize = packingSize;
            _typeSize = typeSize;
            SetParent(parent);
            _declaringType = enclosingType;
 
            // Extract namespace from fullName
            int idx = _name.LastIndexOf('.');
            if (idx != -1)
            {
                _namespace = _name[..idx];
                _name = _name[(idx + 1)..];
            }
 
            if (interfaces != null)
            {
                _interfaces = new List<Type>(interfaces.Length);
                for (int i = 0; i < interfaces.Length; i++)
                {
                    Type @interface = interfaces[i];
                    // cannot contain null in the interface list
                    ArgumentNullException.ThrowIfNull(@interface, nameof(interfaces));
                    _interfaces.Add(@interface);
                }
            }
        }
 
        internal ModuleBuilderImpl GetModuleBuilder() => _module;
        protected override PackingSize PackingSizeCore => _packingSize;
        protected override int SizeCore => _typeSize;
 
        protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes.All))] Type interfaceType)
        {
            ThrowIfCreated();
 
            _interfaces ??= new List<Type>();
            _interfaces.Add(interfaceType);
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2083:DynamicallyAccessedMembers", Justification = "Not sure how to handle warning on 'this'")]
        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        protected override TypeInfo CreateTypeInfoCore()
        {
            if (_isCreated)
            {
                return this;
            }
 
            if (_isHiddenGlobalType)
            {
                _isCreated = true;
                return null!;
            }
 
            // Create a public default constructor if this class has no constructor. Except the type is Interface, ValueType, Enum, or a static class.
            // (TypeAttributes.Abstract | TypeAttributes.Sealed) determines if the type is static
            if (_constructorDefinitions.Count == 0 && (_attributes & TypeAttributes.Interface) == 0 && !IsValueType &&
                ((_attributes & (TypeAttributes.Abstract | TypeAttributes.Sealed)) != (TypeAttributes.Abstract | TypeAttributes.Sealed)))
            {
                DefineDefaultConstructor(MethodAttributes.Public);
            }
 
            ValidateMethods();
            _isCreated = true;
 
            return this;
        }
 
        private void ValidateMethods()
        {
            for (int i = 0; i < _methodDefinitions.Count; i++)
            {
                MethodBuilderImpl method = _methodDefinitions[i];
                MethodAttributes methodAttrs = method.Attributes;
 
                // Any of these flags in the implementation flags is set, we will not check the IL method body
                if (((method.GetMethodImplementationFlags() & (MethodImplAttributes.CodeTypeMask | MethodImplAttributes.PreserveSig | MethodImplAttributes.Unmanaged)) != MethodImplAttributes.IL) ||
                    ((methodAttrs & MethodAttributes.PinvokeImpl) != 0))
                {
                    continue;
                }
 
                ILGeneratorImpl? body = method.ILGeneratorImpl;
                if ((methodAttrs & MethodAttributes.Abstract) != 0)
                {
                    // Check if an abstract method declared on a non-abstract class
                    if ((_attributes & TypeAttributes.Abstract) == 0)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_BadTypeAttributesNotAbstract);
                    }
 
                    // If this is an abstract method or an interface should not have body.
                    if (body != null && body.ILOffset > 0)
                    {
                        throw new InvalidOperationException(SR.Format(SR.InvalidOperation_BadMethodBody, method.Name));
                    }
                }
                else if ((body == null || body.ILOffset == 0) && !method._canBeRuntimeImpl)
                {
                    throw new InvalidOperationException(SR.Format(SR.InvalidOperation_BadEmptyMethodBody, method.Name));
                }
            }
        }
 
        internal void ThrowIfCreated()
        {
            if (_isCreated)
            {
                throw new InvalidOperationException(SR.InvalidOperation_TypeHasBeenCreated);
            }
        }
 
        protected override ConstructorBuilder DefineConstructorCore(MethodAttributes attributes, CallingConventions callingConvention,
            Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers)
        {
            if ((_attributes & TypeAttributes.Interface) == TypeAttributes.Interface && (attributes & MethodAttributes.Static) != MethodAttributes.Static)
            {
                throw new InvalidOperationException(SR.InvalidOperation_ConstructorNotAllowedOnInterface);
            }
 
            ThrowIfCreated();
 
            string name;
            if ((attributes & MethodAttributes.Static) == 0)
            {
                name = ConstructorInfo.ConstructorName;
            }
            else
            {
                name = ConstructorInfo.TypeConstructorName;
            }
 
            attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
            ConstructorBuilderImpl constBuilder = new ConstructorBuilderImpl(name, attributes, callingConvention,
                parameterTypes, requiredCustomModifiers, optionalCustomModifiers, _module, this);
            _constructorDefinitions.Add(constBuilder);
            return constBuilder;
        }
 
        protected override ConstructorBuilder DefineDefaultConstructorCore(MethodAttributes attributes)
        {
            if ((_attributes & TypeAttributes.Interface) == TypeAttributes.Interface)
            {
                throw new InvalidOperationException(SR.InvalidOperation_ConstructorNotAllowedOnInterface);
            }
 
            return DefineDefaultConstructorInternal(attributes);
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
            Justification = "GetConstructor is only called on a TypeBuilderInstantiation which is not subject to trimming")]
        private ConstructorBuilderImpl DefineDefaultConstructorInternal(MethodAttributes attributes)
        {
            // Get the parent class's default constructor and add it to the IL
            ConstructorInfo? con;
            if (_typeParent!.IsConstructedGenericType &&
                (_typeParent.GetGenericTypeDefinition() is TypeBuilderImpl || _module.ContainsTypeBuilder(_typeParent.GetGenericArguments())))
            {
                // When TypeBuilder involved need to construct the parent constructor using TypeBuilder.GetConstructor() static method
                con = GetConstructor(_typeParent, _typeParent.GetGenericTypeDefinition().GetConstructor(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null)!);
            }
            else
            {
                con = _typeParent.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null);
            }
 
            if (con == null)
            {
                throw new NotSupportedException(SR.NotSupported_NoParentDefaultConstructor);
            }
 
            ConstructorBuilderImpl constBuilder = (ConstructorBuilderImpl)DefineConstructorCore(attributes, CallingConventions.Standard, null, null, null);
 
            // generate the code to call the parent's default constructor
            ILGenerator il = constBuilder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, con);
            il.Emit(OpCodes.Ret);
 
            constBuilder._isDefaultConstructor = true;
            return constBuilder;
        }
 
        protected override EventBuilder DefineEventCore(string name, EventAttributes attributes, Type eventtype)
        {
            ArgumentNullException.ThrowIfNull(eventtype);
            ThrowIfCreated();
 
            EventBuilderImpl eventBuilder = new EventBuilderImpl(name, attributes, eventtype, this);
            _eventDefinitions.Add(eventBuilder);
            return eventBuilder;
        }
 
        protected override FieldBuilder DefineFieldCore(string fieldName, Type type, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers, FieldAttributes attributes)
        {
            ThrowIfCreated();
 
            if (_enumUnderlyingType == null && IsEnum)
            {
                if ((attributes & FieldAttributes.Static) == 0)
                {
                    // remember the underlying type for enum type
                    _enumUnderlyingType = type;
                }
            }
 
            var field = new FieldBuilderImpl(this, fieldName, type, attributes, requiredCustomModifiers, optionalCustomModifiers);
            _fieldDefinitions.Add(field);
            return field;
        }
 
        protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names)
        {
            if (_typeParameters != null)
            {
                throw new InvalidOperationException();
            }
 
            var typeParameters = new GenericTypeParameterBuilderImpl[names.Length];
            for (int i = 0; i < names.Length; i++)
            {
                string name = names[i];
                ArgumentNullException.ThrowIfNull(name, nameof(names));
                typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this);
            }
 
            return _typeParameters = typeParameters;
        }
 
        protected override FieldBuilder DefineInitializedDataCore(string name, byte[] data, FieldAttributes attributes)
        {
            if (data.Length <= 0 || data.Length >= 0x003f0000)
            {
                throw new ArgumentException(SR.Argument_BadSizeForData, nameof(data.Length));
            }
 
            // This method will define an initialized Data in .sdata.
            // We will create a fake TypeDef to represent the data with size. This TypeDef
            // will be the signature for the Field.
            return DefineDataHelper(name, data, data.Length, attributes);
        }
 
        protected override MethodBuilder DefineMethodCore(string name, MethodAttributes attributes, CallingConventions callingConvention,
            Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
            Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
        {
            ThrowIfCreated();
 
            MethodBuilderImpl methodBuilder = new(name, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers,
                returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, _module, this);
            _methodDefinitions.Add(methodBuilder);
            return methodBuilder;
        }
 
        protected override void DefineMethodOverrideCore(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
        {
            ThrowIfCreated();
            if (!ReferenceEquals(methodInfoBody.DeclaringType, this))
            {
                // Loader restriction: body method has to be from this class
                throw new ArgumentException(SR.ArgumentException_BadMethodImplBody);
            }
            Type baseType = methodInfoDeclaration.DeclaringType!;
            _methodOverrides ??= new();
 
            if (_methodOverrides.TryGetValue(baseType, out List<(MethodInfo ifaceMethod, MethodInfo targetMethod)>? im))
            {
                if (im.Exists(pair => pair.ifaceMethod.Equals(methodInfoDeclaration)))
                {
                    throw new ArgumentException(SR.Format(SR.Argument_MethodOverridden, methodInfoBody.Name, FullName), nameof(methodInfoDeclaration));
                }
 
                im.Add((methodInfoDeclaration, methodInfoBody));
            }
            else
            {
                im = new List<(MethodInfo ifaceMethod, MethodInfo targetMethod)>();
                im.Add((methodInfoDeclaration, methodInfoBody));
                _methodOverrides.Add(baseType, im);
            }
        }
 
        private bool IsInterfaceImplemented(Type interfaceType)
        {
            if (_interfaces != null)
            {
                foreach (Type iface in _interfaces)
                {
                    if (interfaceType.IsAssignableFrom(iface))
                    {
                        return true;
                    }
                }
            }
 
            if (_typeParent != null)
            {
                foreach (Type @interface in _typeParent.GetInterfaces())
                {
                    if (interfaceType.IsAssignableFrom(@interface))
                    {
                        return true;
                    }
                }
            }
 
            return false;
        }
 
        private ArgumentException ArgumentExceptionInvalidMethodOverride(string methodName) =>
            new ArgumentException(SR.Format(SR.Argument_InvalidMethodOverride, FullName, methodName), "methodInfoBody");
 
        protected override TypeBuilder DefineNestedTypeCore(string name, TypeAttributes attr,
            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packSize, int typeSize)
        {
            return _module.DefineNestedType(name, attr, parent, interfaces, packSize, typeSize, this);
        }
 
        [RequiresUnreferencedCode("P/Invoke marshalling may dynamically access members that could be trimmed.")]
        protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes,
            CallingConventions callingConvention, Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
            Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers, CallingConvention nativeCallConv, CharSet nativeCharSet)
        {
            if ((attributes & MethodAttributes.Abstract) != 0)
            {
                throw new ArgumentException(SR.Argument_BadPInvokeMethod);
            }
 
            if ((_attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
            {
                throw new ArgumentException(SR.Argument_BadPInvokeOnInterface);
            }
 
            ThrowIfCreated();
 
            attributes |= MethodAttributes.PinvokeImpl;
            MethodBuilderImpl method = new MethodBuilderImpl(name, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers,
                returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, _module, this);
            method.CreateDllImportData(dllName, entryName, nativeCallConv, nativeCharSet);
 
            if (_methodDefinitions.Contains(method))
            {
                throw new ArgumentException(SR.Argument_MethodRedefined);
            }
            _methodDefinitions.Add(method);
 
            return method;
        }
 
        protected override PropertyBuilder DefinePropertyCore(string name, PropertyAttributes attributes, CallingConventions callingConvention,
            Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
            Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
        {
            PropertyBuilderImpl property = new PropertyBuilderImpl(name, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers,
                returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, this);
            _propertyDefinitions.Add(property);
            return property;
        }
 
        protected override ConstructorBuilder DefineTypeInitializerCore()
        {
            ThrowIfCreated();
 
            const MethodAttributes attr = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
 
            return new ConstructorBuilderImpl(ConstructorInfo.TypeConstructorName, attr, CallingConventions.Standard, null, null, null, _module, this);
        }
 
        protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes)
        {
            if (size <= 0 || size >= 0x003f0000)
            {
                throw new ArgumentException(SR.Argument_BadSizeForData, nameof(size));
            }
 
            // This method will define an uninitialized Data in .sdata.
            // We will create a fake TypeDef to represent the data with size. This TypeDef
            // will be the signature for the Field.
            return DefineDataHelper(name, new byte[size], size, attributes);
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:DynamicallyAccessedMembers", Justification = "The members of 'ValueType' are not referenced in this context")]
        private FieldBuilder DefineDataHelper(string name, byte[] data, int size, FieldAttributes attributes)
        {
            ArgumentException.ThrowIfNullOrEmpty(name);
 
            ThrowIfCreated();
 
            // form the value class name
            string strValueClassName = $"$ArrayType${size}";
 
            // Is this already defined in this module?
            TypeBuilderImpl? valueClassType = _module.FindTypeBuilderWithName(strValueClassName, false);
 
            if (valueClassType == null)
            {
                TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.ExplicitLayout | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass;
 
                // Define the backing value class
                valueClassType = (TypeBuilderImpl)_module.DefineType(strValueClassName, typeAttributes, _module.GetTypeFromCoreAssembly(CoreTypeId.ValueType), PackingSize.Size1, size);
                valueClassType.CreateType();
            }
 
            FieldBuilder fdBuilder = DefineField(name, valueClassType, attributes | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
 
            // now we need to set the RVA
            ((FieldBuilderImpl)fdBuilder).SetData(data);
            return fdBuilder;
        }
 
        protected override bool IsCreatedCore() => _isCreated;
 
        protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
        {
            // Handle pseudo custom attributes
            switch (con.ReflectedType!.FullName)
            {
                case "System.Runtime.InteropServices.StructLayoutAttribute":
                    ParseStructLayoutAttribute(con, binaryAttribute);
                    return;
                case "System.Runtime.CompilerServices.SpecialNameAttribute":
                    _attributes |= TypeAttributes.SpecialName;
                    return;
                case "System.SerializableAttribute":
#pragma warning disable SYSLIB0050 // 'TypeAttributes.Serializable' is obsolete: 'Formatter-based serialization is obsolete and should not be used'.
                    _attributes |= TypeAttributes.Serializable;
#pragma warning restore SYSLIB0050
                    return;
                case "System.Runtime.InteropServices.ComImportAttribute":
                    _attributes |= TypeAttributes.Import;
                    return;
                case "System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeImportAttribute":
                    _attributes |= TypeAttributes.WindowsRuntime;
                    return;
                case "System.Security.SuppressUnmanagedCodeSecurityAttribute": // It says has no effect in .NET Core, maybe remove?
                    _attributes |= TypeAttributes.HasSecurity;
                    break;
            }
 
            _customAttributes ??= new List<CustomAttributeWrapper>();
            _customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
        }
 
        internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
        {
            SetCustomAttributeCore(con, binaryAttribute);
        }
 
        private void ParseStructLayoutAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
        {
            CustomAttributeInfo attributeInfo = CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute);
            LayoutKind layoutKind = (LayoutKind)attributeInfo._ctorArgs[0]!;
            _attributes &= ~TypeAttributes.LayoutMask;
            _attributes |= layoutKind switch
            {
                LayoutKind.Auto => TypeAttributes.AutoLayout,
                LayoutKind.Explicit => TypeAttributes.ExplicitLayout,
                LayoutKind.Sequential => TypeAttributes.SequentialLayout,
                _ => TypeAttributes.AutoLayout,
            };
 
            for (int i = 0; i < attributeInfo._namedParamNames.Length; ++i)
            {
                string name = attributeInfo._namedParamNames[i];
                int value = (int)attributeInfo._namedParamValues[i]!;
 
                switch (name)
                {
                    case "CharSet":
                        switch ((CharSet)value)
                        {
                            case CharSet.None:
                            case CharSet.Ansi:
                                _attributes &= ~(TypeAttributes.UnicodeClass | TypeAttributes.AutoClass);
                                break;
                            case CharSet.Unicode:
                                _attributes &= ~TypeAttributes.AutoClass;
                                _attributes |= TypeAttributes.UnicodeClass;
                                break;
                            case CharSet.Auto:
                                _attributes &= ~TypeAttributes.UnicodeClass;
                                _attributes |= TypeAttributes.AutoClass;
                                break;
                        }
                        break;
                    case "Pack":
                        _packingSize = (PackingSize)value;
                        break;
                    case "Size":
                        _typeSize = value;
                        break;
                    default:
                        throw new ArgumentException(SR.Format(SR.Argument_UnknownNamedType, con.DeclaringType, name), nameof(binaryAttribute));
                }
            }
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2074:DynamicallyAccessedMembers",
            Justification = "System.Object type is preserved via ModulBuilderImpl.s_coreTypes")]
        protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent)
        {
            ThrowIfCreated();
 
            if (parent != null)
            {
                if (parent.IsInterface)
                {
                    throw new ArgumentException(SR.Argument_CannotSetParentToInterface);
                }
 
                _typeParent = parent;
            }
            else
            {
                if ((_attributes & TypeAttributes.Interface) != TypeAttributes.Interface)
                {
                    _typeParent = _module.GetTypeFromCoreAssembly(CoreTypeId.Object);
                }
                else
                {
                    if ((_attributes & TypeAttributes.Abstract) == 0)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_BadInterfaceNotAbstract);
                    }
 
                    // There is no extends for interface class.
                    _typeParent = null;
                }
            }
        }
        public override string Name => _name;
        public override Type? DeclaringType => _declaringType;
        public override Type? ReflectedType => _declaringType;
        public override bool IsGenericTypeDefinition => IsGenericType;
        public override bool IsConstructedGenericType => false;
        public override bool IsGenericType => _typeParameters != null;
        // Not returning a copy for compat with existing runtime behavior
        public override Type[] GenericTypeParameters => _typeParameters ?? EmptyTypes;
        public override Type[] GetGenericArguments() => _typeParameters ?? EmptyTypes;
        public override Type GetGenericTypeDefinition()
        {
            if (IsGenericTypeDefinition)
            {
                return this;
            }
 
            throw new InvalidOperationException();
        }
        public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
        public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
        public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
        // You will never have to deal with a TypeBuilder if you are just referring to arrays.
        public override Type GetElementType() => throw new NotSupportedException(SR.NotSupported_DynamicModule);
        public override string? AssemblyQualifiedName => throw new NotSupportedException();
        public override string? FullName => _strFullName ??= TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
        public override string? Namespace => _namespace;
        public override Assembly Assembly => _module.Assembly;
        public override Module Module => _module;
        public override Type UnderlyingSystemType => this;
 
        public override Type GetEnumUnderlyingType()
        {
            if (IsEnum)
            {
                if (_enumUnderlyingType == null)
                {
                    throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum);
                }
 
                return _enumUnderlyingType;
            }
            else
            {
                throw new ArgumentException(SR.Argument_MustBeEnum);
            }
        }
        public override bool IsSZArray => false;
        public override Guid GUID => throw new NotSupportedException();
        public override Type? BaseType => _typeParent;
        public override int MetadataToken => MetadataTokens.GetToken(_handle);
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
            DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
            DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
            DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
        public override object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target,
            object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException();
        protected override bool IsArrayImpl() => false;
        protected override bool IsByRefImpl() => false;
        protected override bool IsPointerImpl() => false;
        protected override bool IsPrimitiveImpl() => false;
        protected override bool IsValueTypeImpl() => IsSubclassOf(_module.GetTypeFromCoreAssembly(CoreTypeId.ValueType));
        protected override bool HasElementTypeImpl() => false;
        protected override TypeAttributes GetAttributeFlagsImpl() => _attributes;
        protected override bool IsCOMObjectImpl()
        {
            return ((GetAttributeFlagsImpl() & TypeAttributes.Import) != 0) ? true : false;
        }
 
        internal void ThrowIfNotCreated()
        {
            if (!_isCreated)
            {
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
            }
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
        protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder,
                CallingConventions callConvention, Type[] types, ParameterModifier[]? _)
        {
            ThrowIfNotCreated();
            ArgumentNullException.ThrowIfNull(types);
 
            for (int i = 0; i < types.Length; i++)
            {
                ArgumentNullException.ThrowIfNull(types[i], nameof(types));
            }
 
            foreach (ConstructorBuilderImpl con in _constructorDefinitions)
            {
                if (MatchesTheFilter(con._methodBuilder, GetBindingFlags(con._methodBuilder), bindingAttr, callConvention, types))
                {
                    return con;
                }
            }
 
            return null;
        }
 
        internal static BindingFlags GetBindingFlags(MethodInfo method)
        {
            BindingFlags bindingFlags = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public ?
                BindingFlags.Public : BindingFlags.NonPublic;
            bindingFlags |= (method.Attributes & MethodAttributes.Static) != 0 ? BindingFlags.Static : BindingFlags.Instance;
 
            return bindingFlags;
        }
 
        private static bool MatchesTheFilter(MethodBuilderImpl method, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[]? argumentTypes)
        {
            if ((bindingFlags & methodFlags) != methodFlags)
            {
                return false;
            }
 
            if ((callConv & CallingConventions.Any) == 0)
            {
                if ((callConv & CallingConventions.VarArgs) != 0 && (method.CallingConvention & CallingConventions.VarArgs) == 0)
                {
                    return false;
                }
 
                if ((callConv & CallingConventions.Standard) != 0 && (method.CallingConvention & CallingConventions.Standard) == 0)
                {
                    return false;
                }
            }
 
            if (argumentTypes == null)
            {
                // Not filtering by parameter types
                return true;
            }
 
            Type[] parameterTypes = method.ParameterTypes ?? EmptyTypes;
            if (argumentTypes.Length != parameterTypes.Length)
            {
                return false;
            }
 
            for (int i = 0; i < parameterTypes.Length; i++)
            {
                Type? argType = argumentTypes[i];
                Type? paramType = parameterTypes[i];
 
                if (argType.IsArray != paramType.IsArray ||
                    argType.IsByRef != paramType.IsByRef ||
                    argType.IsPointer != argType.IsPointer)
                {
                    return false;
                }
 
                if (argType.HasElementType || paramType.HasElementType)
                {
                    argType = argType.GetElementType();
                    paramType = paramType.GetElementType();
                }
 
                if (argType == null || !argType.Equals(paramType))
                {
                    return false;
                }
            }
 
            return true;
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
        private ConstructorInfo[] GetConstructors(string name, BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
            ConstructorInfo[] candidates = GetConstructors(bindingAttr);
            List<ConstructorInfo> constructors = new List<ConstructorInfo>();
 
            foreach (ConstructorInfo ctor in candidates)
            {
                if (name == ctor.Name)
                {
                    constructors.Add(ctor);
                }
            }
 
            return constructors.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
        public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
 
            List<ConstructorInfo> ctors = new();
            foreach (ConstructorBuilderImpl con in _constructorDefinitions)
            {
                if (MatchesTheFilter(con._methodBuilder, GetBindingFlags(con._methodBuilder), bindingAttr, CallingConventions.Any, con._methodBuilder.ParameterTypes))
                {
                    ctors.Add(con);
                }
            }
 
            return ctors.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
        public override EventInfo[] GetEvents() => throw new NotSupportedException();
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
        public override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotSupportedException();
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
        public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
        private MethodInfo[] GetMethods(string name, BindingFlags bindingAttr)
        {
            ArgumentNullException.ThrowIfNull(name);
 
            MethodInfo[] candidates = GetMethods(bindingAttr);
            List<MethodInfo> methods = new List<MethodInfo>();
            foreach (MethodInfo method in candidates)
            {
                if (name == method.Name)
                {
                    methods.Add(method);
                }
            }
 
            return methods.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
        public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
 
            List<MethodInfo> methods = new List<MethodInfo>();
            foreach (MethodBuilderImpl method in _methodDefinitions)
            {
                if (!method.IsConstructor && MatchesTheFilter(method, GetBindingFlags(method), bindingAttr, CallingConventions.Any, method.ParameterTypes))
                {
                    methods.Add(method);
                }
            }
 
            if (!bindingAttr.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
            {
                methods.AddRange(_typeParent.GetMethods(bindingAttr));
            }
 
            return methods.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
        protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
                CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
        {
            ThrowIfNotCreated();
 
            MethodInfo? found = null;
            foreach (MethodBuilderImpl method in _methodDefinitions)
            {
                if (name.Equals(method.Name) && MatchesTheFilter(method, GetBindingFlags(method), bindingAttr, callConvention, types))
                {
                    if (found != null)
                    {
                        throw new AmbiguousMatchException(SR.Format(SR.AmbiguousMatch_MemberInfo, method.DeclaringType, method.Name));
                    }
 
                    found = method;
                }
            }
 
            if (found == null && !bindingAttr.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
            {
                if (types == null)
                {
                    found = _typeParent.GetMethod(name, bindingAttr);
                }
                else
                {
                    found = _typeParent.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
                }
            }
 
            return found;
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
        public override FieldInfo? GetField(string name, BindingFlags bindingFlags)
        {
            ArgumentNullException.ThrowIfNull(name);
            ThrowIfNotCreated();
 
            FieldInfo? match = null;
            StringComparison compare = (bindingFlags & BindingFlags.IgnoreCase) != 0 ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
            foreach (FieldBuilderImpl fieldInfo in _fieldDefinitions)
            {
                BindingFlags fieldFlags = GetBindingFlags(fieldInfo);
                if (name.Equals(fieldInfo.Name, compare) && (bindingFlags & fieldFlags) == fieldFlags)
                {
                    if (match != null && ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType))
                    {
                        // TypeBuilder doesn't validate for duplicates when fields are defined, throw if duplicates found.
                        throw new AmbiguousMatchException(SR.Format(SR.AmbiguousMatch_MemberInfo, fieldInfo.DeclaringType, fieldInfo.Name));
                    }
 
                    match = fieldInfo;
                }
            }
 
            if (match == null && !bindingFlags.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
            {
                match = _typeParent.GetField(name, bindingFlags);
            }
 
            return match;
        }
 
        private static BindingFlags GetBindingFlags(FieldBuilderImpl field)
        {
            BindingFlags bindingFlags = (field.Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public ?
                BindingFlags.Public : BindingFlags.NonPublic;
 
            bindingFlags |= (field.Attributes & FieldAttributes.Static) != 0 ? BindingFlags.Static : BindingFlags.Instance;
 
            return bindingFlags;
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
        private FieldInfo[] GetFields(string name, BindingFlags bindingAttr)
        {
            ArgumentNullException.ThrowIfNull(name);
            ThrowIfNotCreated();
 
            FieldInfo[] candidates = GetFields(bindingAttr);
            List<FieldInfo> fields = new List<FieldInfo>();
 
            foreach (FieldInfo field in candidates)
            {
                if (name == field.Name)
                {
                    fields.Add(field);
                }
            }
 
            return fields.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
        public override FieldInfo[] GetFields(BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
 
            List<FieldInfo> fields = new List<FieldInfo>(_fieldDefinitions.Count);
            foreach (FieldBuilderImpl fieldInfo in _fieldDefinitions)
            {
                BindingFlags fieldFlags = GetBindingFlags(fieldInfo);
                if ((bindingAttr & fieldFlags) == fieldFlags)
                {
                    fields.Add(fieldInfo);
                }
            }
 
            if (!bindingAttr.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
            {
                 fields.AddRange(_typeParent.GetFields(bindingAttr));
            }
 
            return fields.ToArray();
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2063:UnrecognizedReflectionPattern")]
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
        public override Type? GetInterface(string name, bool ignoreCase)
        {
            ArgumentNullException.ThrowIfNull(name);
            ThrowIfNotCreated();
 
            Type[] interfaces = GetInterfaces();
 
            Type? match = null;
            StringComparison compare = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
            for (int i = 0; i < interfaces.Length; ++i)
            {
                Type interfaceType = interfaces[i];
 
                if (name.Equals(interfaceType.Name, compare))
                {
                    if (match != null)
                    {
                        // TypeBuilder doesn't validate for duplicates when fields are defined, throw if duplicates found.
                        throw new AmbiguousMatchException(SR.Format(SR.AmbiguousMatch_MemberInfo, interfaceType.DeclaringType, interfaceType.Name));
                    }
 
                    match = interfaceType;
                }
            }
 
            return match;
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
        public override Type[] GetInterfaces()
        {
            ThrowIfNotCreated();
 
            List<Type> interfaces = _interfaces ?? [];
 
            if(_typeParent != null)
            {
                interfaces.AddRange(_typeParent.GetInterfaces());
            }
 
            return interfaces.ToArray();
        }
 
        internal static BindingFlags GetBindingFlags(PropertyBuilderImpl property)
        {
            MethodInfo? getMethod = property.GetMethod;
            MethodInfo? setMethod = property.SetMethod;
 
            BindingFlags bindingFlags = BindingFlags.Default;
 
            if (getMethod != null)
            {
                bindingFlags = GetBindingFlags(getMethod);
            }
            else if (setMethod != null)
            {
                bindingFlags = GetBindingFlags(setMethod);
            }
 
            return bindingFlags;
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
        private PropertyInfo[] GetProperties(string name, BindingFlags bindingAttr)
        {
            ArgumentNullException.ThrowIfNull(name);
 
            PropertyInfo[] candidates = GetProperties(bindingAttr);
            List<PropertyInfo> properties = new List<PropertyInfo>();
            foreach (PropertyInfo property in candidates)
            {
                if (name == property.Name)
                {
                    properties.Add(property);
                }
            }
 
            return properties.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
        public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
 
            List<PropertyInfo> candidates = new List<PropertyInfo>(_propertyDefinitions.Count);
            foreach (PropertyBuilderImpl property in _propertyDefinitions)
            {
                BindingFlags flags = GetBindingFlags(property);
                if ((bindingAttr & flags) == flags)
                {
                    candidates.Add(property);
                }
            }
 
            if (!bindingAttr.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
            {
                candidates.AddRange(_typeParent.GetProperties(bindingAttr));
            }
 
            return candidates.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
        protected override PropertyInfo? GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder,
                Type? returnType, Type[]? types, ParameterModifier[]? modifiers)
        {
            ArgumentNullException.ThrowIfNull(name);
 
            List<PropertyInfo> candidates = GetPropertyCandidates(name, bindingAttr, types);
 
            if (candidates.Count == 0)
                return null;
 
            if (types == null || types.Length == 0)
            {
                // no arguments
                PropertyInfo firstCandidate = candidates[0];
 
                if (candidates.Count == 1)
                {
                    if (returnType is not null && !returnType.IsEquivalentTo(firstCandidate.PropertyType))
                        return null;
 
                    return firstCandidate;
                }
                else
                {
                    if (returnType is null)
                    {
                        // if we are here we have no args or property type to select over and we have more than one property with that name
                        throw new AmbiguousMatchException(SR.Format(SR.AmbiguousMatch_MemberInfo, firstCandidate.DeclaringType, firstCandidate.Name));
                    }
                }
            }
 
            binder ??= DefaultBinder;
            return binder.SelectProperty(bindingAttr, candidates.ToArray(), returnType, types, modifiers);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
        private List<PropertyInfo> GetPropertyCandidates(string name, BindingFlags bindingAttr, Type[]? types)
        {
            PropertyInfo[] properties = GetProperties(bindingAttr);
 
            List<PropertyInfo> candidates = new List<PropertyInfo>(properties.Length);
            for (int i = 0; i < properties.Length; i++)
            {
                PropertyInfo propertyInfo = properties[i];
                if (propertyInfo.Name == name &&
                    (types == null || (propertyInfo.GetIndexParameters().Length == types.Length)))
                {
                    candidates.Add(propertyInfo);
                }
            }
 
            return candidates;
        }
 
        private static BindingFlags GetBindingFlags(TypeBuilderImpl type)
        {
            BindingFlags bindingFlags = type.IsPublic || type.IsNestedPublic ? BindingFlags.Public : BindingFlags.NonPublic;
 
            return bindingFlags;
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
        private Type[] GetNestedTypes(string name, BindingFlags bindingAttr)
        {
            ArgumentNullException.ThrowIfNull(name);
            ThrowIfNotCreated();
 
            Type[] candidates = GetNestedTypes(bindingAttr);
            List<Type> nestedTypes = new List<Type>();
 
            foreach (Type type in candidates)
            {
                if (type.Name == name)
                {
                    nestedTypes.Add(type);
                }
            }
 
            return nestedTypes.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
        public override Type[] GetNestedTypes(BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
 
            List<Type> nestedTypes = new List<Type>();
            foreach (TypeBuilderImpl type in _module.GetNestedTypeBuilders(this))
            {
                BindingFlags typeFlags = GetBindingFlags(type);
                if ((bindingAttr & typeFlags) == typeFlags)
                {
                    nestedTypes.Add(type);
                }
            }
 
            return nestedTypes.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
        public override Type? GetNestedType(string name, BindingFlags bindingAttr)
        {
            ArgumentNullException.ThrowIfNull(name);
 
            Type[] types = GetNestedTypes(bindingAttr);
 
            Type? match = null;
            foreach (Type type in types)
            {
                if (type.Name == name)
                {
                    if (match != null)
                    {
                        throw new AmbiguousMatchException(SR.Format(SR.AmbiguousMatch_MemberInfo, type.DeclaringType, type.Name));
                    }
 
                    match = type;
                }
            }
 
            return match;
        }
 
        [DynamicallyAccessedMembers(GetAllMembers)]
        public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
        {
            ArgumentNullException.ThrowIfNull(name);
 
            MethodInfo[] methods = [];
            ConstructorInfo[] constructors = [];
            PropertyInfo[] properties = [];
            EventInfo[] events = [];
            FieldInfo[] fields = [];
            Type[] nestedTypes = [];
 
            int totalCount = 0;
 
            // Methods
            if ((type & MemberTypes.Method) != 0)
            {
                methods = GetMethods(name, bindingAttr);
                if (type == MemberTypes.Method)
                    return methods;
                totalCount += methods.Length;
            }
 
            // Constructors
            if ((type & MemberTypes.Constructor) != 0)
            {
                constructors = GetConstructors(name, bindingAttr);
                if (type == MemberTypes.Constructor)
                    return constructors;
                totalCount += constructors.Length;
            }
 
            // Properties
            if ((type & MemberTypes.Property) != 0)
            {
                properties = GetProperties(name, bindingAttr);
                if (type == MemberTypes.Property)
                    return properties;
                totalCount += properties.Length;
            }
 
            // Missing in TypeBuilderImpl
            // Events
            //if ((type & MemberTypes.Event) != 0)
            //{
            //    events = GetEventCandidates(name, bindingAttr, true);
            //    if (type == MemberTypes.Event)
            //        return events.ToArray();
            //    totalCount += events.Count;
            //}
 
            // Fields
            if ((type & MemberTypes.Field) != 0)
            {
                fields = GetFields(name, bindingAttr);
                if (type == MemberTypes.Field)
                    return fields;
                totalCount += fields.Length;
            }
 
            // NestedTypes
            if ((type & (MemberTypes.NestedType | MemberTypes.TypeInfo)) != 0)
            {
                nestedTypes = GetNestedTypes(name, bindingAttr);
                if (type == MemberTypes.NestedType || type == MemberTypes.TypeInfo)
                    return nestedTypes;
                totalCount += nestedTypes.Length;
            }
 
            MemberInfo[] compressMembers = (type == (MemberTypes.Method | MemberTypes.Constructor)) ?
                new MethodBase[totalCount] : new MemberInfo[totalCount];
 
            int i = 0;
            methods.CopyTo(compressMembers, i); i += methods.Length;
            constructors.CopyTo(compressMembers, i); i += constructors.Length;
            properties.CopyTo(compressMembers, i); i += properties.Length;
            events.CopyTo(compressMembers, i); i += events.Length;
            fields.CopyTo(compressMembers, i); i += fields.Length;
            nestedTypes.CopyTo(compressMembers, i);
 
            return compressMembers;
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2085:DynamicallyAccessedMembers", Justification = "Methods are loaded from this TypeBuilder")]
        public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
        {
            ThrowIfNotCreated();
            ArgumentNullException.ThrowIfNull(interfaceType);
            ValidateInterfaceType(interfaceType);
 
            MethodInfo[] interfaceMethods = interfaceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            InterfaceMapping im = new InterfaceMapping
            {
                InterfaceType = interfaceType,
                TargetType = this,
                InterfaceMethods = new MethodInfo[interfaceMethods.Length],
                TargetMethods = new MethodInfo[interfaceMethods.Length]
            };
 
            for (int i = 0; i < interfaceMethods.Length; i++)
            {
                MethodInfo interfaceMethod = interfaceMethods[i];
                MethodInfo? targetMethod = GetMethodImpl(interfaceMethod.Name, GetBindingFlags(interfaceMethod), null, interfaceMethod.CallingConvention, GetParameterTypes(interfaceMethod.GetParameters()), null);
 
                im.InterfaceMethods[i] = interfaceMethod;
                im.TargetMethods[i] = targetMethod!;
            }
 
            if (_methodOverrides == null)
            {
                return im;
            }
 
            // Add the interface implementations defined with 'DefineMethodOverride',
            // this overrides default implementations if there is any
            if (_methodOverrides.TryGetValue(interfaceType, out var mapping))
            {
                for (int i = 0; i < interfaceMethods.Length; i++)
                {
                    for (int j = 0; j < mapping.Count; j++)
                    {
                        if (im.InterfaceMethods[i].Equals(mapping[j].ifaceMethod))
                        {
                            im.TargetMethods[i] = mapping[j].targetMethod;
                        }
                    }
                }
            }
 
            return im;
        }
 
        private static Type[] GetParameterTypes(ParameterInfo[] parameterInfos)
        {
            Type[] parameterTypes = new Type[parameterInfos.Length];
            for (int i = 0; i < parameterInfos.Length; i++)
            {
                parameterTypes[i] = parameterInfos[i].ParameterType;
            }
            return parameterTypes;
        }
 
        private void ValidateInterfaceType(Type interfaceType)
        {
            if (!interfaceType.IsInterface)
            {
                throw new ArgumentException(SR.Argument_MustBeInterface, nameof(interfaceType));
            }
 
            if (!IsInterfaceImplemented(interfaceType))
            {
                throw new ArgumentException(SR.Argument_InterfaceNotFound, nameof(interfaceType));
            }
 
            if (IsGenericParameter)
            {
                throw new InvalidOperationException(SR.Argument_GenericParameter);
            }
        }
 
        [DynamicallyAccessedMembers(GetAllMembers)]
        public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
        {
            ThrowIfNotCreated();
 
            MethodInfo[] methods = GetMethods(bindingAttr);
            ConstructorInfo[] constructors = GetConstructors(bindingAttr);
            PropertyInfo[] properties = GetProperties(bindingAttr);
            // EventInfo[] events = GetEvents(bindingAttr); // missing in TypeBuilderImpl
            FieldInfo[] fields = GetFields(bindingAttr);
            Type[] nestedTypes = GetNestedTypes(bindingAttr);
 
            // Interfaces are excluded from the result of GetMembers
 
            MemberInfo[] members = new MemberInfo[
                methods.Length +
                constructors.Length +
                properties.Length +
                // events.Length +
                fields.Length +
                nestedTypes.Length];
 
            int i = 0;
            methods.CopyTo(members, i); i += methods.Length;
            constructors.CopyTo(members, i); i += constructors.Length;
            properties.CopyTo(members, i); i += properties.Length;
            //events.CopyTo(members, i); i += events.Length;
            fields.CopyTo(members, i); i += fields.Length;
            nestedTypes.CopyTo(members, i);
 
            return members;
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
            Justification = "The GetInterfaces technically requires all interfaces to be preserved" +
                "But in this case it acts only on TypeBuilder which is never trimmed (as it's runtime created).")]
        public override bool IsAssignableFrom([NotNullWhen(true)] Type? c)
        {
            if (AreTypesEqual(this, c))
            {
                return true;
            }
 
            if (c is TypeBuilderImpl tb)
            {
                if (tb.IsSubclassOf(this))
                {
                    return true;
                }
 
                // in order to be a parent of interface this should be an interface
                if (!IsInterface)
                {
                    return false;
                }
 
                Type[] interfaces = tb.GetInterfaces();
                for (int i = 0; i < interfaces.Length; i++)
                {
                    // IsSubclassOf does not cover the case when they are the same type.
                    if (AreTypesEqual(interfaces[i], this))
                    {
                        return true;
                    }
 
                    if (interfaces[i].IsSubclassOf(this))
                    {
                        return true;
                    }
                }
            }
 
            return false;
        }
 
        internal static bool AreTypesEqual(Type t1, Type? t2)
        {
            if (t1 == t2)
            {
                return true;
            }
 
            if (t1 is TypeBuilderImpl rtb1)
            {
                if (t2 is TypeBuilderImpl tb && ReferenceEquals(rtb1, tb))
                {
                    return true;
                }
            }
 
            return false;
        }
 
        public override bool IsSubclassOf(Type c)
        {
            Type? p = this;
 
            if (AreTypesEqual(p, c))
            {
                return false;
            }
 
            p = p.BaseType;
 
            while (p != null)
            {
                if (AreTypesEqual(p, c))
                {
                    return true;
                }
 
                p = p.BaseType;
            }
 
            return false;
        }
 
        internal const DynamicallyAccessedMemberTypes GetAllMembers = DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
            DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
            DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents |
            DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
            DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors |
            DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
    }
}