File: System\Reflection\Runtime\MethodInfos\RuntimeConstructorInfo.cs
Web Access
Project: src\src\runtime\src\coreclr\nativeaot\System.Private.CoreLib\src\System.Private.CoreLib.csproj (System.Private.CoreLib)
// 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;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Runtime.ParameterInfos;

using Internal.Reflection.Core.Execution;

namespace System.Reflection.Runtime.MethodInfos
{
    //
    // The runtime's implementation of ConstructorInfo.
    //
    internal abstract partial class RuntimeConstructorInfo : ConstructorInfo
    {
        public abstract override MethodAttributes Attributes { get; }

        public abstract override CallingConventions CallingConvention { get; }

        public sealed override bool ContainsGenericParameters
        {
            get
            {
                return DeclaringType.ContainsGenericParameters;
            }
        }

        public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; }

        public abstract override Type DeclaringType { get; }

        [RequiresUnreferencedCode("Trimming may change method bodies. For example it can change some instructions, remove branches or local variables.")]
        public sealed override MethodBody GetMethodBody()
        {
            throw new PlatformNotSupportedException();
        }

        public sealed override ParameterInfo[] GetParameters()
        {
            RuntimeParameterInfo[] parameters = RuntimeParameters;
            if (parameters.Length == 0)
                return Array.Empty<ParameterInfo>();
            ParameterInfo[] result = new ParameterInfo[parameters.Length];
            for (int i = 0; i < result.Length; i++)
                result[i] = parameters[i];
            return result;
        }

        public sealed override ReadOnlySpan<ParameterInfo> GetParametersAsSpan()
        {
            return RuntimeParameters;
        }

        public abstract override bool HasSameMetadataDefinitionAs(MemberInfo other);

        public abstract override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture);

        [DebuggerGuidedStepThrough]
        public sealed override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
        {
            parameters ??= Array.Empty<object>();
            MethodBaseInvoker methodInvoker;
            try
            {
                methodInvoker = this.MethodInvoker;
            }
            catch (Exception)
            {
                //
                // Project N compat note: On the desktop, ConstructorInfo.Invoke(Object[]) specifically forbids invoking static constructors (and
                // for us, that check is embedded inside the MethodInvoker property call.) Howver, MethodBase.Invoke(Object, Object[]) allows it. This was
                // probably an oversight on the desktop. We choose not to support this loophole on Project N for the following reasons:
                //
                //  1. The Project N toolchain aggressively replaces static constructors with static initialization data whenever possible.
                //     So the static constructor may no longer exist.
                //
                //  2. Invoking the static constructor through Reflection is not very useful as it invokes the static constructor whether or not
                //     it was already run. Since static constructors are specifically one-shot deals, this will almost certainly mess up the
                //     type's internal assumptions.
                //

                if (this.IsStatic)
                    throw new PlatformNotSupportedException(SR.Acc_NotClassInit);
                throw;
            }

            object? result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture);
            DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
            return result!;
        }

        internal abstract override MethodBase MetadataDefinitionMethod { get; }

        public abstract override int MetadataToken
        {
            get;
        }

        public sealed override Module Module
        {
            get
            {
                return DeclaringType.Module;
            }
        }

        public sealed override bool IsConstructedGenericMethod
        {
            get
            {
                return false;
            }
        }

        public sealed override bool IsGenericMethod
        {
            get
            {
                return false;
            }
        }

        public sealed override bool IsGenericMethodDefinition
        {
            get
            {
                return false;
            }
        }

        public abstract override MethodImplAttributes MethodImplementationFlags { get; }

        public abstract override string Name { get; }

        public abstract override bool Equals(object obj);

        public abstract override int GetHashCode();

        public sealed override Type ReflectedType
        {
            get
            {
                // Constructors are always looked up as if BindingFlags.DeclaredOnly were specified. Thus, the ReflectedType will always be the DeclaringType.
                return DeclaringType;
            }
        }

        public abstract override string ToString();

        public abstract override RuntimeMethodHandle MethodHandle { get; }

        protected internal MethodBaseInvoker MethodInvoker
        {
            get
            {
                return _lazyMethodInvoker ??= UncachedMethodInvoker;
            }
        }

        internal IntPtr LdFtnResult => MethodInvoker.LdFtnResult;

        protected abstract RuntimeParameterInfo[] RuntimeParameters { get; }

        protected abstract MethodBaseInvoker UncachedMethodInvoker { get; }

        private volatile MethodBaseInvoker _lazyMethodInvoker;
    }
}