File: System\Activator.NativeAot.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.

//
// Activator is an object that contains the Activation (CreateInstance/New)
//  methods for late bound support.
//

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;

using Internal.Reflection.Augments;
using Internal.Runtime;
using Internal.Runtime.CompilerServices;

namespace System
{
    public static partial class Activator
    {
        // The following methods and helper class implement the functionality of Activator.CreateInstance<T>()
        // The implementation relies on several compiler intrinsics that expand to quick dictionary lookups in shared
        // code, and direct constant references in unshared code.
        //
        // This method is the public surface area. It wraps the CreateInstance intrinsic with the appropriate try/catch
        // block so that the correct exceptions are generated. Also, it handles the cases where the T type doesn't have
        // a default constructor.
        //
        // This method is intrinsic. The compiler might replace it with more efficient implementation.
        [DebuggerGuidedStepThrough]
        [Intrinsic]
        public static unsafe T CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] T>()
        {
            // Grab the pointer to the default constructor of the type. If T doesn't have a default
            // constructor, the intrinsic returns a marker pointer that we check for.
            IntPtr defaultConstructor = DefaultConstructorOf<T>();

            // Check if we got the marker back.
            //
            // TODO: might want to disambiguate the different cases for abstract class, interface, etc.
            if (defaultConstructor == (IntPtr)(delegate*<Guid>)&MissingConstructorMethod)
                throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, typeof(T)));

            T t;
            try
            {
                // Call the default constructor on the allocated instance.
                if (!typeof(T).IsValueType)
                {
                    // Grab a pointer to the optimized allocator for the type and call it.
                    IntPtr allocator = AllocatorOf<T>();
                    t = RawCalliHelper.Call<T>(allocator, (nint)MethodTable.Of<T>());
                    RawCalliHelper.Call(defaultConstructor, t);

                    // Debugger goo so that stepping in works. Only affects debug info generation.
                    // The call gets optimized away.
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                else
                {
                    t = default!;
                    RawCalliHelper.CallDefaultStructConstructor(defaultConstructor, ref Unsafe.As<T, byte>(ref t));

                    // Debugger goo so that stepping in works. Only affects debug info generation.
                    // The call gets optimized away.
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }

                return t;
            }
            catch (Exception e)
            {
                throw new TargetInvocationException(e);
            }
        }

        [Intrinsic]
        private static IntPtr DefaultConstructorOf<T>()
        {
            // Codegens must expand this intrinsic to the pointer to the default constructor of T
            // or to a marker that lets us detect there's no default constructor.
            // We could implement a fallback with the type loader if we wanted to, but it will be slow and unreliable.
            throw new NotSupportedException();
        }

        [Intrinsic]
        private static IntPtr AllocatorOf<T>()
        {
            // Codegens must expand this intrinsic to the pointer to the allocator suitable to allocate an instance of T.
            // We could implement a fallback with the type loader if we wanted to, but it will be slow and unreliable.
            throw new NotSupportedException();
        }

        internal static unsafe IntPtr GetFallbackDefaultConstructor()
        {
            return (IntPtr)(delegate*<Guid>)&MissingConstructorMethod;
        }

        // This is a marker method. We return a GUID just to make sure the body is unique
        // and under no circumstances gets folded.
        private static Guid MissingConstructorMethod() => new Guid(0x68be9718, 0xf787, 0x45ab, 0x84, 0x3b, 0x1f, 0x31, 0xb6, 0x12, 0x65, 0xeb);
        // The constructor of this struct is used when there's no constructor
        private struct StructWithNoConstructor { public StructWithNoConstructor() { } }

        [DebuggerHidden]
        [DebuggerStepThrough]
        public static object? CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type, bool nonPublic)
            => ReflectionAugments.ActivatorCreateInstance(type, nonPublic);

        [DebuggerHidden]
        [DebuggerStepThrough]
        public static object? CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicConstructors)] Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes)
            => ReflectionAugments.ActivatorCreateInstance(type, bindingAttr, binder, args, culture, activationAttributes);

        [RequiresUnreferencedCode("Type and its constructor could be removed")]
        public static ObjectHandle CreateInstance(string assemblyName, string typeName)
        {
            throw new PlatformNotSupportedException(); // https://github.com/dotnet/runtime/issues/26701
        }

        [RequiresUnreferencedCode("Type and its constructor could be removed")]
        public static ObjectHandle CreateInstance(string assemblyName,
                                                  string typeName,
                                                  bool ignoreCase,
                                                  BindingFlags bindingAttr,
                                                  Binder? binder,
                                                  object?[]? args,
                                                  CultureInfo? culture,
                                                  object?[]? activationAttributes)
        {
            throw new PlatformNotSupportedException(); // https://github.com/dotnet/runtime/issues/26701
        }

        [RequiresUnreferencedCode("Type and its constructor could be removed")]
        public static ObjectHandle CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes)
        {
            throw new PlatformNotSupportedException(); // https://github.com/dotnet/runtime/issues/26701
        }
    }
}